10_FRM.pm 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. ##############################################
  2. # $Id: 10_FRM.pm 15021 2017-09-06 19:48:55Z klausw $
  3. ##############################################
  4. package main;
  5. use vars qw{%attr %defs};
  6. use strict;
  7. use warnings;
  8. use GPUtils qw(:all);
  9. #add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
  10. BEGIN {
  11. if (!grep(/FHEM\/lib$/,@INC)) {
  12. foreach my $inc (grep(/FHEM$/,@INC)) {
  13. push @INC,$inc."/lib";
  14. };
  15. };
  16. };
  17. use Device::Firmata::Constants qw/ :all /;
  18. use Device::Firmata::Protocol;
  19. use Device::Firmata::Platform;
  20. sub FRM_Set($@);
  21. sub FRM_Attr(@);
  22. my %sets = (
  23. "reset" => "",
  24. "reinit" => ""
  25. );
  26. my %gets = (
  27. "firmware" => "",
  28. "version" => ""
  29. );
  30. my @clients = qw(
  31. FRM_IN
  32. FRM_OUT
  33. FRM_AD
  34. FRM_PWM
  35. FRM_I2C
  36. FRM_SERVO
  37. FRM_RGB
  38. FRM_ROTENC
  39. FRM_STEPPER
  40. OWX
  41. OWX_ASYNC
  42. I2C_LCD
  43. I2C_DS1307
  44. I2C_PC.*
  45. I2C_MCP23.*
  46. I2C_SHT.*
  47. I2C_BME280
  48. I2C_BMP180
  49. I2C_BH1750
  50. I2C_TSL2561
  51. FRM_LCD
  52. I2C_K30
  53. I2C_LM.*
  54. );
  55. #####################################
  56. sub FRM_Initialize($) {
  57. my $hash = shift @_;
  58. require "$main::attr{global}{modpath}/FHEM/DevIo.pm";
  59. # Provider
  60. $hash->{Clients} = join (':',@clients);
  61. $hash->{ReadyFn} = "FRM_Ready";
  62. $hash->{ReadFn} = "FRM_Read";
  63. $hash->{I2CWrtFn} = "FRM_I2C_Write";
  64. # Consumer
  65. $hash->{DefFn} = "FRM_Define";
  66. $hash->{UndefFn} = "FRM_Undef";
  67. $hash->{GetFn} = "FRM_Get";
  68. $hash->{SetFn} = "FRM_Set";
  69. $hash->{AttrFn} = "FRM_Attr";
  70. $hash->{NotifyFn} = "FRM_Notify";
  71. $hash->{AttrList} = "model:nano dummy:1,0 sampling-interval i2c-config $main::readingFnAttributes";
  72. }
  73. #####################################
  74. sub FRM_Define($$) {
  75. my ( $hash, $def ) = @_;
  76. my ($name, $type, $dev, $global) = split("[ \t]+", $def);
  77. $hash->{DeviceName} = $dev;
  78. $hash->{NOTIFYDEV} = "global";
  79. if ( $dev eq "none" ) {
  80. Log3 $name,3,"device is none, commands will be echoed only";
  81. $main::attr{$name}{dummy} = 1;
  82. }
  83. if ($main::init_done) {
  84. return FRM_Start($hash);
  85. }
  86. return undef;
  87. }
  88. #####################################
  89. sub FRM_Undef($) {
  90. my $hash = shift;
  91. FRM_forall_clients($hash,\&FRM_Client_Unassign,undef);
  92. if (defined $hash->{DeviceName}) {
  93. DevIo_Disconnected($hash);
  94. };
  95. TcpServer_Close($hash);
  96. foreach my $d ( sort keys %main::defs ) { # close and dispose open tcp-connection (if any) to free open filedescriptors
  97. if ( defined( my $dev = $main::defs{$d} )) {
  98. if ( defined( $main::defs{$d}{SNAME} )
  99. && $main::defs{$d}{SNAME} eq $hash->{NAME}) {
  100. FRM_Tcp_Connection_Close($main::defs{$d});
  101. }
  102. }
  103. }
  104. FRM_FirmataDevice_Close($hash);
  105. return undef;
  106. }
  107. sub FRM_Start {
  108. my ($hash) = @_;
  109. my ($dev, $global) = split("[ \t]+", $hash->{DEF});
  110. $hash->{DeviceName} = $dev;
  111. my $isServer = 1 if($dev && $dev =~ m/^(IPV6:)?\d+$/);
  112. # my $isClient = 1 if($dev && $dev =~ m/^(IPV6:)?.*:\d+$/);
  113. # return "Usage: define <name> FRM {<device>[@<baudrate>] | [IPV6:]<tcp-portnr> [global]}"
  114. # if(!($isServer || $isClient) ||
  115. # ($isClient && $global) ||
  116. # ($global && $global ne "global"));
  117. # Make sure that fhem only runs once
  118. if($isServer) {
  119. my $ret = TcpServer_Open($hash, $dev, $global);
  120. if (!$ret) {
  121. $hash->{STATE}="listening";
  122. }
  123. return $ret;
  124. }
  125. DevIo_CloseDev($hash);
  126. my $ret = DevIo_OpenDev($hash, 0, "FRM_DoInit");
  127. return $ret;
  128. }
  129. sub FRM_Notify {
  130. my ($hash,$dev) = @_;
  131. my $name = $hash->{NAME};
  132. my $type = $hash->{TYPE};
  133. if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
  134. FRM_Start($hash);
  135. } elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
  136. }
  137. }
  138. #####################################
  139. sub FRM_is_firmata_connected {
  140. my ($hash) = @_;
  141. return defined($hash->{FirmataDevice}) && defined ($hash->{FirmataDevice}->{io});
  142. }
  143. #####################################
  144. sub FRM_Set($@) {
  145. my ($hash, @a) = @_;
  146. return "Need at least one parameters" if(@a < 2);
  147. return "Unknown argument $a[1], choose one of " . join(" ", sort keys %sets)
  148. if(!defined($sets{$a[1]}));
  149. my $command = $a[1];
  150. my $value = $a[2];
  151. COMMAND_HANDLER: {
  152. $command eq "reset" and do {
  153. return $hash->{NAME}." is not connected" unless (FRM_is_firmata_connected($hash) && (defined $hash->{FD} or ($^O=~/Win/ and defined $hash->{USBDev})));
  154. $hash->{FirmataDevice}->system_reset();
  155. if (defined $hash->{SERVERSOCKET}) {
  156. # dispose preexisting connections
  157. foreach my $e ( sort keys %main::defs ) {
  158. if ( defined( my $dev = $main::defs{$e} )) {
  159. if ( defined( $dev->{SNAME} ) && ( $dev->{SNAME} eq $hash->{NAME} )) {
  160. FRM_Tcp_Connection_Close($dev);
  161. }
  162. }
  163. }
  164. FRM_FirmataDevice_Close($hash);
  165. last;
  166. } else {
  167. DevIo_CloseDev($hash);
  168. FRM_FirmataDevice_Close($hash);
  169. return DevIo_OpenDev($hash, 0, "FRM_DoInit");
  170. }
  171. };
  172. $command eq "reinit" and do {
  173. FRM_forall_clients($hash,\&FRM_Init_Client,undef);
  174. last;
  175. };
  176. }
  177. return undef;
  178. }
  179. #####################################
  180. sub FRM_Get($@) {
  181. my ($hash, @a) = @_;
  182. return "Need at least one parameters" if(@a < 2);
  183. return "Unknown argument $a[1], choose one of " . join(" ", sort keys %gets)
  184. if(!defined($gets{$a[1]}));
  185. my $name = shift @a;
  186. my $cmd = shift @a;
  187. ARGUMENT_HANDLER: {
  188. $cmd eq "firmware" and do {
  189. if (FRM_is_firmata_connected($hash)) {
  190. return $hash->{FirmataDevice}->{metadata}->{firmware};
  191. } else {
  192. return "not connected to FirmataDevice";
  193. }
  194. };
  195. $cmd eq "version" and do {
  196. if (FRM_is_firmata_connected($hash)) {
  197. return $hash->{FirmataDevice}->{metadata}->{firmware_version};
  198. } else {
  199. return "not connected to FirmataDevice";
  200. }
  201. };
  202. }
  203. }
  204. #####################################
  205. # called from the global loop, when the select for hash->{FD} reports data
  206. sub FRM_Read($) {
  207. my ( $hash ) = @_;
  208. if($hash->{SERVERSOCKET}) { # Accept and create a child
  209. my $chash = TcpServer_Accept($hash, "FRM");
  210. return if(!$chash);
  211. $chash->{DeviceName}=$hash->{PORT}; # required for DevIo_CloseDev and FRM_Ready
  212. $chash->{TCPDev}=$chash->{CD};
  213. # dispose preexisting connections
  214. foreach my $e ( sort keys %main::defs ) {
  215. if ( defined( my $dev = $main::defs{$e} )) {
  216. if ( $dev != $chash && defined( $dev->{SNAME} ) && ( $dev->{SNAME} eq $chash->{SNAME} )) {
  217. FRM_Tcp_Connection_Close($dev);
  218. }
  219. }
  220. }
  221. FRM_FirmataDevice_Close($hash);
  222. FRM_DoInit($chash);
  223. return;
  224. }
  225. my $device = $hash->{FirmataDevice} or return;
  226. $device->poll();
  227. }
  228. sub FRM_Ready($) {
  229. my ($hash) = @_;
  230. my $name = $hash->{NAME};
  231. if ($name=~/^^FRM:.+:\d+$/) { # this is a closed tcp-connection, remove it
  232. FRM_Tcp_Connection_Close($hash);
  233. FRM_FirmataDevice_Close($hash);
  234. }
  235. return DevIo_OpenDev($hash, 1, "FRM_DoInit") if($hash->{STATE} eq "disconnected");
  236. # This is relevant for windows/USB only
  237. my $po = $hash->{USBDev};
  238. my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
  239. if($po) {
  240. ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
  241. }
  242. return ($InBytes && $InBytes>0);
  243. }
  244. sub FRM_Tcp_Connection_Close($) {
  245. my $hash = shift;
  246. TcpServer_Close($hash);
  247. if ($hash->{SNAME}) {
  248. my $shash = $main::defs{$hash->{SNAME}};
  249. if (defined $shash) {
  250. $shash->{STATE}="listening";
  251. delete $shash->{SocketDevice} if (defined $shash->{SocketDevice});
  252. }
  253. }
  254. my $dev = $hash->{DeviceName};
  255. my $name = $hash->{NAME};
  256. if (defined $name) {
  257. delete $main::readyfnlist{"$name.$dev"} if (defined $dev);
  258. delete $main::attr{$name};
  259. delete $main::defs{$name};
  260. }
  261. return undef;
  262. }
  263. sub FRM_FirmataDevice_Close($) {
  264. my $hash = shift;
  265. my $device = $hash->{FirmataDevice};
  266. if (defined $device) {
  267. if (defined $device->{io}) {
  268. delete $hash->{FirmataDevice}->{io}->{handle} if defined $hash->{FirmataDevice}->{io}->{handle};
  269. delete $hash->{FirmataDevice}->{io};
  270. }
  271. delete $device->{protocol} if defined $device->{protocol};
  272. delete $hash->{FirmataDevice};
  273. }
  274. }
  275. sub FRM_Attr(@) {
  276. my ($command,$name,$attribute,$value) = @_;
  277. if ($command eq "set") {
  278. $main::attr{$name}{$attribute}=$value;
  279. if ($attribute eq "sampling-interval"
  280. or $attribute eq "i2c-config") {
  281. FRM_apply_attribute($main::defs{$name},$attribute);
  282. }
  283. }
  284. }
  285. sub FRM_apply_attribute {
  286. my ($hash,$attribute) = @_;
  287. my $firmata = $hash->{FirmataDevice};
  288. my $name = $hash->{NAME};
  289. if (defined $firmata) {
  290. if ($attribute eq "sampling-interval") {
  291. $firmata->sampling_interval(AttrVal($name,$attribute,"1000"));
  292. } elsif ($attribute eq "i2c-config") {
  293. my $i2cattr = AttrVal($name,$attribute,undef);
  294. if (defined $i2cattr) {
  295. my @a = split(" ", $i2cattr);
  296. my $i2cpins = $firmata->{metadata}{i2c_pins};
  297. my $err;
  298. if (defined $i2cpins and scalar @$i2cpins) {
  299. eval {
  300. foreach my $i2cpin (@$i2cpins) {
  301. $firmata->pin_mode($i2cpin,PIN_I2C);
  302. }
  303. $firmata->i2c_config(@a);
  304. $firmata->observe_i2c(\&FRM_i2c_observer,$hash);
  305. };
  306. $err = $@ if ($@);
  307. } else {
  308. $err = "Error, arduino doesn't support I2C";
  309. }
  310. Log3 $name,2,$err if ($err);
  311. }
  312. }
  313. }
  314. }
  315. sub FRM_DoInit($) {
  316. my ($hash) = @_;
  317. my $sname = $hash->{SNAME}; #is this a serversocket-connection?
  318. my $shash = defined $sname ? $main::defs{$sname} : $hash;
  319. my $name = $shash->{NAME};
  320. my $firmata_io = Firmata_IO->new($hash,$name);
  321. my $device = Device::Firmata::Platform->attach($firmata_io) or return 1;
  322. $shash->{FirmataDevice} = $device;
  323. if (defined $sname) {
  324. $shash->{SocketDevice} = $hash;
  325. #as FRM_Read gets the connected socket hash, but calls firmatadevice->poll():
  326. $hash->{FirmataDevice} = $device;
  327. }
  328. $device->observe_string(\&FRM_string_observer,$shash);
  329. my $found; # we cannot call $device->probe() here, as it doesn't select bevore read, so it would likely cause IODev to close the connection on the first attempt to read from empty stream
  330. my $endTicks = time+5;
  331. my $queryTicks = time+2;
  332. $device->system_reset();
  333. do {
  334. FRM_poll($shash);
  335. if ($device->{metadata}{firmware} && $device->{metadata}{firmware_version}) {
  336. $device->{protocol}->{protocol_version} = $device->{metadata}{firmware_version};
  337. $main::defs{$name}{firmware} = $device->{metadata}{firmware};
  338. $main::defs{$name}{firmware_version} = $device->{metadata}{firmware_version};
  339. Log3 $name,3,"Firmata Firmware Version: ".$device->{metadata}{firmware}." ".$device->{metadata}{firmware_version};
  340. $device->analog_mapping_query();
  341. $device->capability_query();
  342. do {
  343. FRM_poll($shash);
  344. if ($device->{metadata}{analog_mappings} and $device->{metadata}{capabilities}) {
  345. my $inputpins = $device->{metadata}{input_pins};
  346. $main::defs{$name}{input_pins} = join(",", sort{$a<=>$b}(@$inputpins)) if (defined $inputpins and scalar @$inputpins);
  347. my $outputpins = $device->{metadata}{output_pins};
  348. $main::defs{$name}{output_pins} = join(",", sort{$a<=>$b}(@$outputpins)) if (defined $outputpins and scalar @$outputpins);
  349. my $analogpins = $device->{metadata}{analog_pins};
  350. $main::defs{$name}{analog_pins} = join(",", sort{$a<=>$b}(@$analogpins)) if (defined $analogpins and scalar @$analogpins);
  351. my $pwmpins = $device->{metadata}{pwm_pins};
  352. $main::defs{$name}{pwm_pins} = join(",", sort{$a<=>$b}(@$pwmpins)) if (defined $pwmpins and scalar @$pwmpins);
  353. my $servopins = $device->{metadata}{servo_pins};
  354. $main::defs{$name}{servo_pins} = join(",", sort{$a<=>$b}(@$servopins)) if (defined $servopins and scalar @$servopins);
  355. my $i2cpins = $device->{metadata}{i2c_pins};
  356. $main::defs{$name}{i2c_pins} = join(",", sort{$a<=>$b}(@$i2cpins)) if (defined $i2cpins and scalar @$i2cpins);
  357. my $onewirepins = $device->{metadata}{onewire_pins};
  358. $main::defs{$name}{onewire_pins} = join(",", sort{$a<=>$b}(@$onewirepins)) if (defined $onewirepins and scalar @$onewirepins);
  359. my $encoderpins = $device->{metadata}{encoder_pins};
  360. $main::defs{$name}{encoder_pins} = join(",", sort{$a<=>$b}(@$encoderpins)) if (defined $encoderpins and scalar @$encoderpins);
  361. my $stepperpins = $device->{metadata}{stepper_pins};
  362. $main::defs{$name}{stepper_pins} = join(",", sort{$a<=>$b}(@$stepperpins)) if (defined $stepperpins and scalar @$stepperpins);
  363. if (defined $device->{metadata}{analog_resolutions}) {
  364. my @analog_resolutions;
  365. foreach my $pin (sort{$a<=>$b}(keys %{$device->{metadata}{analog_resolutions}})) {
  366. push @analog_resolutions,$pin.":".$device->{metadata}{analog_resolutions}{$pin};
  367. }
  368. $main::defs{$name}{analog_resolutions} = join(",",@analog_resolutions) if (scalar @analog_resolutions);
  369. }
  370. if (defined $device->{metadata}{pwm_resolutions}) {
  371. my @pwm_resolutions;
  372. foreach my $pin (sort{$a<=>$b}(keys %{$device->{metadata}{pwm_resolutions}})) {
  373. push @pwm_resolutions,$pin.":".$device->{metadata}{pwm_resolutions}{$pin};
  374. }
  375. $main::defs{$name}{pwm_resolutions} = join(",",@pwm_resolutions) if (scalar @pwm_resolutions);
  376. }
  377. if (defined $device->{metadata}{servo_resolutions}) {
  378. my @servo_resolutions;
  379. foreach my $pin (sort{$a<=>$b}(keys %{$device->{metadata}{servo_resolutions}})) {
  380. push @servo_resolutions,$pin.":".$device->{metadata}{servo_resolutions}{$pin};
  381. }
  382. $main::defs{$name}{servo_resolutions} = join(",",@servo_resolutions) if (scalar @servo_resolutions);
  383. }
  384. if (defined $device->{metadata}{encoder_resolutions}) {
  385. my @encoder_resolutions;
  386. foreach my $pin (sort{$a<=>$b}(keys %{$device->{metadata}{encoder_resolutions}})) {
  387. push @encoder_resolutions,$pin.":".$device->{metadata}{encoder_resolutions}{$pin};
  388. }
  389. $main::defs{$name}{encoder_resolutions} = join(",",@encoder_resolutions) if (scalar @encoder_resolutions);
  390. }
  391. if (defined $device->{metadata}{stepper_resolutions}) {
  392. my @stepper_resolutions;
  393. foreach my $pin (sort{$a<=>$b}(keys %{$device->{metadata}{stepper_resolutions}})) {
  394. push @stepper_resolutions,$pin.":".$device->{metadata}{stepper_resolutions}{$pin};
  395. }
  396. $main::defs{$name}{stepper_resolutions} = join(",",@stepper_resolutions) if (scalar @stepper_resolutions);
  397. }
  398. $found = 1;
  399. } else {
  400. select (undef,undef,undef,0.01);
  401. }
  402. } while (time < $endTicks and !$found);
  403. $found = 1;
  404. } else {
  405. select (undef,undef,undef,0.01);
  406. if (time > $queryTicks) {
  407. Log3 $name,3,"querying Firmata Firmware Version";
  408. $device->firmware_version_query();
  409. $queryTicks++;
  410. }
  411. }
  412. } while (time < $endTicks and !$found);
  413. if ($found) {
  414. FRM_apply_attribute($shash,"sampling-interval");
  415. FRM_apply_attribute($shash,"i2c-config");
  416. FRM_forall_clients($shash,\&FRM_Init_Client,undef);
  417. $shash->{STATE}="Initialized";
  418. return undef;
  419. }
  420. Log3 $name,3,"no response from Firmata, closing DevIO";
  421. DevIo_Disconnected($shash);
  422. delete $shash->{FirmataDevice};
  423. delete $shash->{SocketDevice};
  424. return "FirmataDevice not responding";
  425. }
  426. sub
  427. FRM_forall_clients($$$)
  428. {
  429. my ($hash,$fn,$args) = @_;
  430. foreach my $d ( sort keys %main::defs ) {
  431. if ( defined( $main::defs{$d} )
  432. && defined( $main::defs{$d}{IODev} )
  433. && $main::defs{$d}{IODev} == $hash ) {
  434. &$fn($main::defs{$d},$args);
  435. }
  436. }
  437. return undef;
  438. }
  439. sub
  440. FRM_Init_Client($@) {
  441. my ($hash,$args) = @_;
  442. if (!defined $args and defined $hash->{DEF}) {
  443. my @a = split("[ \t][ \t]*", $hash->{DEF});
  444. $args = \@a;
  445. }
  446. my $name = $hash->{NAME};
  447. my $ret = CallFn($name,"InitFn",$hash,$args);
  448. if ($ret) {
  449. Log3 $name,2,"error initializing '".$hash->{NAME}."': ".$ret;
  450. }
  451. }
  452. sub
  453. FRM_Init_Pin_Client($$$) {
  454. my ($hash,$args,$mode) = @_;
  455. my $u = "wrong syntax: define <name> FRM_XXX pin";
  456. return $u unless defined $args and int(@$args) > 0;
  457. my $pin = @$args[0];
  458. $hash->{PIN} = $pin;
  459. eval {
  460. FRM_Client_AssignIOPort($hash);
  461. FRM_Client_FirmataDevice($hash)->pin_mode($pin,$mode);
  462. };
  463. if ($@) {
  464. $@ =~ /^(.*)( at.*FHEM.*)$/;
  465. $hash->{STATE} = "error initializing: ".$1;
  466. return $1;
  467. }
  468. return undef;
  469. }
  470. sub
  471. FRM_Client_Define($$)
  472. {
  473. my ($hash, $def) = @_;
  474. my @a = split("[ \t][ \t]*", $def);
  475. $hash->{STATE}="defined";
  476. if ($main::init_done) {
  477. eval {
  478. FRM_Init_Client($hash,[@a[2..scalar(@a)-1]]);
  479. };
  480. if ($@) {
  481. $@ =~ /^(.*)( at.*FHEM.*)$/;
  482. return $1;
  483. }
  484. }
  485. return undef;
  486. }
  487. sub
  488. FRM_Client_Undef($$)
  489. {
  490. my ($hash, $name) = @_;
  491. my $pin = $hash->{PIN};
  492. eval {
  493. my $firmata = FRM_Client_FirmataDevice($hash);
  494. $firmata->pin_mode($pin,PIN_ANALOG);
  495. };
  496. if ($@) {
  497. eval {
  498. my $firmata = FRM_Client_FirmataDevice($hash);
  499. $firmata->pin_mode($pin,PIN_INPUT);
  500. $firmata->digital_write($pin,0);
  501. };
  502. }
  503. return undef;
  504. }
  505. sub
  506. FRM_Client_Unassign($)
  507. {
  508. my ($dev) = @_;
  509. delete $dev->{IODev} if defined $dev->{IODev};
  510. $dev->{STATE}="defined";
  511. }
  512. sub
  513. FRM_Client_AssignIOPort($@)
  514. {
  515. my ($hash,$iodev) = @_;
  516. my $name = $hash->{NAME};
  517. AssignIoPort($hash,defined $iodev ? $iodev : AttrVal($hash->{NAME},"IODev",undef));
  518. die "unable to assign IODev to '$name'" unless defined ($hash->{IODev});
  519. if (defined($hash->{IODev}->{SNAME})) {
  520. $hash->{IODev} = $main::defs{$hash->{IODev}->{SNAME}};
  521. $attr{$name}{IODev} = $hash->{IODev}{NAME};
  522. }
  523. foreach my $d ( sort keys %main::defs ) {
  524. if ( defined( my $dev = $main::defs{$d} )) {
  525. if ( $dev != $hash
  526. && defined( $dev->{IODev} )
  527. && defined( $dev->{PIN} )
  528. && $dev->{IODev} == $hash->{IODev}
  529. && defined( $hash->{PIN})
  530. && grep {$_ == $hash->{PIN}} split(" ",$dev->{PIN}) ) {
  531. delete $hash->{IODev};
  532. delete $attr{$name}{IODev};
  533. die "Device '$main::defs{$d}{NAME}' allready defined for pin $hash->{PIN}";
  534. }
  535. }
  536. }
  537. }
  538. sub FRM_Client_FirmataDevice($) {
  539. my $hash = shift;
  540. my $iodev = $hash->{IODev};
  541. die $hash->{NAME}." no IODev assigned" unless defined $iodev;
  542. die $hash->{NAME}.", ".$iodev->{NAME}." is not connected" unless (defined $iodev->{FirmataDevice} and (defined $iodev->{FD} or ($^O=~/Win/ and defined $iodev->{USBDev})));
  543. return $iodev->{FirmataDevice};
  544. }
  545. sub FRM_Catch($) {
  546. my $exception = shift;
  547. if ($exception) {
  548. $exception =~ /^(.*)( at.*FHEM.*)$/;
  549. return $1;
  550. }
  551. return undef;
  552. }
  553. package Firmata_IO;
  554. sub new($$) {
  555. my ($class,$hash,$name) = @_;
  556. return bless {
  557. hash => $hash,
  558. name => $name,
  559. }, $class;
  560. }
  561. sub data_write {
  562. my ( $self, $buf ) = @_;
  563. my $hash = $self->{hash};
  564. main::Log3 $self->{name},5,"FRM:>".unpack "H*",$buf;
  565. main::DevIo_SimpleWrite($hash,$buf,undef);
  566. }
  567. sub data_read {
  568. my ( $self, $bytes ) = @_;
  569. my $hash = $self->{hash};
  570. my $string = main::DevIo_SimpleRead($hash);
  571. if (defined $string ) {
  572. main::Log3 $self->{name},5,"FRM:<".unpack "H*",$string;
  573. }
  574. return $string;
  575. }
  576. package main;
  577. # im master muss eine I2CWrtFn definiert werden, diese wird vom client mit
  578. # CallFn(<mastername>, "I2CWrtFn", <masterhash>, \%sendpackage);
  579. # aufgerufen.
  580. # Der Master muss mit AssignIoPort() dem Client zugeordnet werden;
  581. # %sendpackage muss folgende keys enthalten:
  582. #
  583. # i2caddress => <xx>
  584. # direction => <i2cwrite|i2cread>
  585. # data => <xx [xx ...] (kann für read leer bleiben)>
  586. #
  587. # der Master fügt zu %sendpackage noch folgende keys hinzu:
  588. #
  589. # received (durch leerzeichen getrennte 1byte hexwerte)
  590. # mastername_* (alle mit mastername_ beginnenden keys können als internal im client angelegt weden)
  591. # unter anderem: mastername_SENDSTAT (enthält "Ok" wenn Übertragung erfolgreich)
  592. #
  593. # danach ruft er über:
  594. # CallFn(<clientname>, "I2CRecFn", <clienthash>, $sendpackage);
  595. # die I2CRecFn im client auf. Dort werden die Daten verarbeitet und
  596. # im Master wird der Hash sendpackage gelöscht.
  597. #
  598. # $package->{i2caddress}; # single byte value
  599. # $package->{direction}; # i2cread|i2cwrite
  600. # $package->{data}; # space separated list of values
  601. # $package->{reg}; # register
  602. # $package->{nbyte}; # number of bytes to read
  603. #
  604. # $firmata->i2c_read($address,$register,$bytestoread);
  605. # $firmata->i2c_write($address,@data);
  606. sub FRM_I2C_Write
  607. {
  608. my ($hash,$package) = @_;
  609. if (FRM_is_firmata_connected($hash)) {
  610. my $firmata = $hash->{FirmataDevice};
  611. COMMANDHANDLER: {
  612. $package->{direction} eq "i2cwrite" and do {
  613. if (defined $package->{reg}) {
  614. $firmata->i2c_write($package->{i2caddress},$package->{reg},split(" ",$package->{data}));
  615. } else {
  616. $firmata->i2c_write($package->{i2caddress},split(" ",$package->{data}));
  617. }
  618. last;
  619. };
  620. $package->{direction} eq "i2cread" and do {
  621. if (defined $package->{reg}) {
  622. $firmata->i2c_readonce($package->{i2caddress},$package->{reg},defined $package->{nbyte} ? $package->{nbyte} : 1);
  623. } else {
  624. $firmata->i2c_readonce($package->{i2caddress},defined $package->{nbyte} ? $package->{nbyte} : 1);
  625. }
  626. last;
  627. };
  628. }
  629. }
  630. }
  631. sub
  632. FRM_i2c_observer
  633. {
  634. my ($data,$hash) = @_;
  635. Log3 $hash->{NAME},5,"onI2CMessage address: '".$data->{address}."', register: '".$data->{register}."' data: [".(join(',',@{$data->{data}}))."]";
  636. FRM_forall_clients($hash,\&FRM_i2c_update_device,$data);
  637. }
  638. sub FRM_i2c_update_device
  639. {
  640. my ($hash,$data) = @_;
  641. if (defined $hash->{I2C_Address} and $hash->{I2C_Address} eq $data->{address}) {
  642. CallFn($hash->{NAME}, "I2CRecFn", $hash, {
  643. i2caddress => $data->{address},
  644. direction => "i2cread",
  645. reg => $data->{register},
  646. nbyte => scalar(@{$data->{data}}),
  647. received => join (' ',@{$data->{data}}),
  648. $hash->{IODev}->{NAME}."_SENDSTAT" => "Ok",
  649. });
  650. } elsif (defined $hash->{"i2c-address"} && $hash->{"i2c-address"}==$data->{address}) {
  651. my $replydata = $data->{data};
  652. my @values = split(" ",ReadingsVal($hash->{NAME},"values",""));
  653. splice(@values,$data->{register},@$replydata, @$replydata);
  654. readingsBeginUpdate($hash);
  655. $hash->{STATE}="active";
  656. readingsBulkUpdate($hash,"values",join (" ",@values),1);
  657. readingsEndUpdate($hash,1);
  658. }
  659. }
  660. sub FRM_string_observer
  661. {
  662. my ($string,$hash) = @_;
  663. Log3 $hash->{NAME},3,"received String_data: ".$string;
  664. readingsSingleUpdate($hash,"error",$string,1);
  665. }
  666. sub FRM_poll
  667. {
  668. my ($hash) = @_;
  669. if (defined $hash->{SocketDevice} and defined $hash->{SocketDevice}->{FD}) {
  670. my ($rout, $rin) = ('', '');
  671. vec($rin, $hash->{SocketDevice}->{FD}, 1) = 1;
  672. my $nfound = select($rout=$rin, undef, undef, 0.1);
  673. my $mfound = vec($rout, $hash->{SocketDevice}->{FD}, 1);
  674. if($mfound && FRM_is_firmata_connected($hash)) {
  675. $hash->{FirmataDevice}->poll();
  676. }
  677. return $mfound;
  678. } elsif (defined $hash->{FD}) {
  679. my ($rout, $rin) = ('', '');
  680. vec($rin, $hash->{FD}, 1) = 1;
  681. my $nfound = select($rout=$rin, undef, undef, 0.1);
  682. my $mfound = vec($rout, $hash->{FD}, 1);
  683. if($mfound && FRM_is_firmata_connected($hash)) {
  684. $hash->{FirmataDevice}->poll();
  685. }
  686. return $mfound;
  687. } else {
  688. # This is relevant for windows/USB only
  689. my $po = $hash->{USBDev};
  690. my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
  691. if($po) {
  692. ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
  693. }
  694. if ($InBytes && $InBytes>0 && FRM_is_firmata_connected($hash)) {
  695. $hash->{FirmataDevice}->poll();
  696. }
  697. }
  698. }
  699. ######### following is code to be called from OWX: ##########
  700. sub
  701. FRM_OWX_Init($$)
  702. {
  703. my ($hash,$args) = @_;
  704. my $ret = FRM_Init_Pin_Client($hash,$args,PIN_ONEWIRE);
  705. return $ret if (defined $ret);
  706. eval {
  707. my $firmata = FRM_Client_FirmataDevice($hash);
  708. my $pin = $hash->{PIN};
  709. $hash->{FRM_OWX_CORRELATIONID} = 0;
  710. $firmata->observe_onewire($pin,\&FRM_OWX_observer,$hash);
  711. $hash->{FRM_OWX_REPLIES} = {};
  712. $hash->{DEVS} = [];
  713. if ( AttrVal($hash->{NAME},"buspower","") eq "parasitic" ) {
  714. $firmata->onewire_config($pin,1);
  715. }
  716. };
  717. return GP_Catch($@) if ($@);
  718. $hash->{STATE}="Initialized";
  719. InternalTimer(gettimeofday()+10, "OWX_Discover", $hash,0);
  720. return undef;
  721. }
  722. sub FRM_OWX_observer
  723. {
  724. my ( $data,$hash ) = @_;
  725. my $command = $data->{command};
  726. COMMAND_HANDLER: {
  727. $command eq "READ_REPLY" and do {
  728. my $id = $data->{id};
  729. my $request = (defined $id) ? $hash->{FRM_OWX_REQUESTS}->{$id} : undef;
  730. unless (defined $request) {
  731. return unless (defined $data->{device});
  732. my $owx_device = FRM_OWX_firmata_to_device($data->{device});
  733. my %requests = %{$hash->{FRM_OWX_REQUESTS}};
  734. foreach my $key (keys %requests) {
  735. if ($requests{$key}->{device} eq $owx_device) {
  736. $request = $requests{$key};
  737. $id = $key;
  738. last;
  739. };
  740. };
  741. };
  742. return unless (defined $request);
  743. my $owx_data = pack "C*",@{$data->{data}};
  744. my $owx_device = $request->{device};
  745. $hash->{FRM_OWX_REPLIES}->{$owx_device} = $owx_data;
  746. delete $hash->{FRM_OWX_REQUESTS}->{$id};
  747. last;
  748. };
  749. ($command eq "SEARCH_REPLY" or $command eq "SEARCH_ALARMS_REPLY") and do {
  750. my @owx_devices = ();
  751. foreach my $device (@{$data->{devices}}) {
  752. push @owx_devices, FRM_OWX_firmata_to_device($device);
  753. }
  754. if ($command eq "SEARCH_REPLY") {
  755. $hash->{DEVS} = \@owx_devices;
  756. #$main::attr{$hash->{NAME}}{"ow-devices"} = join " ",@owx_devices;
  757. } else {
  758. $hash->{ALARMDEVS} = \@owx_devices;
  759. }
  760. last;
  761. };
  762. }
  763. }
  764. ########### functions implementing interface to OWX ##########
  765. sub FRM_OWX_device_to_firmata
  766. {
  767. my @device;
  768. foreach my $hbyte (unpack "A2xA2A2A2A2A2A2xA2", shift) {
  769. push @device, hex $hbyte;
  770. }
  771. return {
  772. family => shift @device,
  773. crc => pop @device,
  774. identity => \@device,
  775. }
  776. }
  777. sub FRM_OWX_firmata_to_device
  778. {
  779. my $device = shift;
  780. return sprintf ("%02X.%02X%02X%02X%02X%02X%02X.%02X",$device->{family},@{$device->{identity}},$device->{crc});
  781. }
  782. sub FRM_OWX_Verify {
  783. my ($hash,$dev) = @_;
  784. foreach my $found (@{$hash->{DEVS}}) {
  785. if ($dev eq $found) {
  786. return 1;
  787. }
  788. }
  789. return 0;
  790. }
  791. sub FRM_OWX_Alarms {
  792. my ($hash) = @_;
  793. my $ret = eval {
  794. my $firmata = FRM_Client_FirmataDevice($hash);
  795. my $pin = $hash->{PIN};
  796. return 0 unless ( defined $firmata and defined $pin );
  797. $hash->{ALARMDEVS} = undef;
  798. $firmata->onewire_search_alarms($hash->{PIN});
  799. my $times = AttrVal($hash,"ow-read-timeout",1000) / 50; #timeout in ms, defaults to 1 sec
  800. for (my $i=0;$i<$times;$i++) {
  801. if (FRM_poll($hash->{IODev})) {
  802. if (defined $hash->{ALARMDEVS}) {
  803. return 1;
  804. }
  805. } else {
  806. select (undef,undef,undef,0.05);
  807. }
  808. }
  809. $hash->{ALARMDEVS} = [];
  810. return 1;
  811. };
  812. if ($@) {
  813. Log3 $hash->{NAME},4,"FRM_OWX_Alarms: ".GP_Catch($@);
  814. return 0;
  815. }
  816. return $ret;
  817. }
  818. sub FRM_OWX_Reset {
  819. my ($hash) = @_;
  820. my $ret = eval {
  821. my $firmata = FRM_Client_FirmataDevice($hash);
  822. my $pin = $hash->{PIN};
  823. return undef unless ( defined $firmata and defined $pin );
  824. $firmata->onewire_reset($pin);
  825. return 1;
  826. };
  827. if ($@) {
  828. Log3 $hash->{NAME},4,"FRM_OWX_Alarms: ".GP_Catch($@);
  829. return 0;
  830. }
  831. return $ret;
  832. }
  833. sub FRM_OWX_Complex ($$$$) {
  834. my ( $hash, $owx_dev, $data, $numread ) = @_;
  835. my $res = "";
  836. my $ret = eval {
  837. my $firmata = FRM_Client_FirmataDevice($hash);
  838. my $pin = $hash->{PIN};
  839. return 0 unless ( defined $firmata and defined $pin );
  840. my $ow_command = {};
  841. #-- has match ROM part
  842. if ($owx_dev) {
  843. $ow_command->{"select"} = FRM_OWX_device_to_firmata($owx_dev);
  844. #-- padding first 9 bytes into result string, since we have this
  845. # in the serial interfaces as well
  846. $res .= "000000000";
  847. }
  848. #-- has data part
  849. if ($data) {
  850. my @data = unpack "C*", $data;
  851. $ow_command->{"write"} = \@data;
  852. $res.=$data;
  853. }
  854. #-- has receive part
  855. if ( $numread > 0 ) {
  856. $ow_command->{"read"} = $numread;
  857. #Firmata sends 0-address on read after skip
  858. $owx_dev = '00.000000000000.00' unless defined $owx_dev;
  859. my $id = $hash->{FRM_OWX_CORRELATIONID};
  860. $ow_command->{"id"} = $hash->{FRM_OWX_CORRELATIONID};
  861. $hash->{FRM_OWX_REQUESTS}->{$id} = {
  862. command => $ow_command,
  863. device => $owx_dev
  864. };
  865. delete $hash->{FRM_OWX_REPLIES}->{$owx_dev};
  866. $hash->{FRM_OWX_CORRELATIONID} = ($id + 1) & 0xFFFF;
  867. }
  868. $firmata->onewire_command_series( $pin, $ow_command );
  869. if ($numread) {
  870. my $times = AttrVal($hash,"ow-read-timeout",1000) / 50; #timeout in ms, defaults to 1 sec
  871. for (my $i=0;$i<$times;$i++) {
  872. if (FRM_poll($hash->{IODev})) {
  873. if (defined $hash->{FRM_OWX_REPLIES}->{$owx_dev}) {
  874. $res .= $hash->{FRM_OWX_REPLIES}->{$owx_dev};
  875. return $res;
  876. }
  877. } else {
  878. select (undef,undef,undef,0.05);
  879. }
  880. }
  881. }
  882. return $res;
  883. };
  884. if ($@) {
  885. Log3 $hash->{NAME},4,"FRM_OWX_Alarms: ".GP_Catch($@);
  886. return 0;
  887. }
  888. return $ret;
  889. }
  890. ########################################################################################
  891. #
  892. # OWX_Discover_FRM - Discover devices on the 1-Wire bus via internal firmware
  893. #
  894. # Parameter hash = hash of bus master
  895. #
  896. # Return 0 : error
  897. # 1 : OK
  898. #
  899. ########################################################################################
  900. sub FRM_OWX_Discover ($) {
  901. my ($hash) = @_;
  902. my $ret = eval {
  903. my $firmata = FRM_Client_FirmataDevice($hash);
  904. my $pin = $hash->{PIN};
  905. return 0 unless ( defined $firmata and defined $pin );
  906. my $old_devices = $hash->{DEVS};
  907. $hash->{DEVS} = undef;
  908. $firmata->onewire_search($hash->{PIN});
  909. my $times = AttrVal($hash,"ow-read-timeout",1000) / 50; #timeout in ms, defaults to 1 sec
  910. for (my $i=0;$i<$times;$i++) {
  911. if (FRM_poll($hash->{IODev})) {
  912. if (defined $hash->{DEVS}) {
  913. return 1;
  914. }
  915. } else {
  916. select (undef,undef,undef,0.05);
  917. }
  918. }
  919. $hash->{DEVS} = $old_devices;
  920. return 1;
  921. };
  922. if ($@) {
  923. Log3 $hash->{NAME},4,"FRM_OWX_Alarms: ".GP_Catch($@);
  924. return 0;
  925. }
  926. return $ret;
  927. }
  928. 1;
  929. =pod
  930. =item device
  931. =item summary accesses FRM devices
  932. =item summary_DE Zugriff auf FRM Ger&auml;te
  933. =begin html
  934. CHANGES
  935. 18.12.2015 jensb
  936. o added sub FRM_is_firmata_connected
  937. - extended connection check including {FirmataDevice}->{io} (gets
  938. deleted by FRM_FirmataDevice_Close on TCP disconnect while FHEM
  939. has still a valid reference to {FirmataDevice} when calling
  940. I2CWrtFn)
  941. o modified sub FRM_Set, FRM_Get, FRM_I2C_Write, FRM_poll:
  942. - use sub FRM_is_firmata_connected to check if Firmata is still
  943. connected before performing IO operations (to prevent FHEM crash)
  944. o modified sub FRM_Tcp_Connection_Close:
  945. - set STATE to listening and delete SocketDevice (to present same
  946. idle state as FRM_Start)
  947. o help updated
  948. =cut
  949. =pod
  950. =begin html
  951. <a name="FRM"></a>
  952. <h3>FRM</h3>
  953. <ul>
  954. connects fhem to <a href="http://www.arduino.cc">Arduino</a> using
  955. the <a href="http://www.firmata.org">Firmata</a> protocol.
  956. <br><br>
  957. A single FRM device can serve multiple FRM-clients.<br><br>
  958. Clients of FRM are:<br><br>
  959. <a href="#FRM_IN">FRM_IN</a> for digital input<br>
  960. <a href="#FRM_OUT">FRM_OUT</a> for digital out<br>
  961. <a href="#FRM_AD">FRM_AD</a> for analog input<br>
  962. <a href="#FRM_PWM">FRM_PWM</a> for analog output (pulse_width_modulated)<br>
  963. <a href="#FRM_RGB">FRM_RGB</a> control multichannel/RGB-LEDs by pwm<br>
  964. <a href="#FRM_SERVO">FRM_SERVO</a> for pwm-controled servos as being used in modelmaking<br>
  965. <a href="#FRM_LCD">FRM_LCD</a> output text to LCD attached via I2C<br>
  966. <a href="#FRM_I2C">FRM_I2C</a> to read data from integrated circutes attached
  967. to Arduino supporting the <a href="http://en.wikipedia.org/wiki/I%C2%B2C">
  968. i2c-protocol</a>.<br>
  969. <a href="#OWX">OWX</a> to read/write sensors and actors on 1-Wire bus.<br><br>
  970. Each client stands for a Pin of the Arduino configured for a specific use
  971. (digital/analog in/out) or an integrated circuit connected to Arduino by i2c.<br><br>
  972. Note: this module is based on <a href="https://github.com/ntruchsess/perl-firmata">Device::Firmata</a> module (perl-firmata).
  973. perl-firmata is included in FHEM-distributions lib-directory. You can download the latest version <a href="https://github.com/amimoto/perl-firmata/archive/master.zip">as a single zip</a> file from github.<br><br>
  974. Note: this module may require the Device::SerialPort or Win32::SerialPort
  975. module if you attach the device via USB and the OS sets strange default
  976. parameters for serial devices.<br><br>
  977. <a name="FRMdefine"></a>
  978. <b>Define</b><br>
  979. <ul><br>
  980. <code>define &lt;name&gt; FRM {&lt;device&gt; | &lt;port&gt; [global]}</code> <br>
  981. Specifies the FRM device.<br>
  982. <br>
  983. <li>USB-connected devices:<br><br>
  984. <code>&lt;device&gt;</code> specifies the serial port to communicate with the Arduino.
  985. The name of the serial-device depends on your distribution, under
  986. linux the cdc_acm kernel module is responsible, and usually a
  987. /dev/ttyACM0 device will be created. If your distribution does not have a
  988. cdc_acm module, you can force usbserial to handle the Arduino by the
  989. following command:<br>
  990. <code>modprobe usbserial vendor=0x03eb product=0x204b</code></br>
  991. In this case the device is most probably /dev/ttyUSB0.<br><br>
  992. You can also specify a baudrate if the device name contains the @
  993. character, e.g.: /dev/ttyACM0@38400<br><br>
  994. If the baudrate is "directio" (e.g.: /dev/ttyACM0@directio), then the
  995. perl module Device::SerialPort is not needed, and fhem opens the device
  996. with simple file io. This might work if the operating system uses sane
  997. defaults for the serial parameters, e.g. some Linux distributions and
  998. OSX. <br><br>
  999. The Arduino has to run either 'StandardFirmata' or 'ConfigurableFirmata'.
  1000. StandardFirmata supports Digital and Analog-I/O, Servo and I2C. In addition
  1001. to that ConfigurableFirmata supports 1-Wire and Stepper-motors.<br><br>
  1002. You can find StandardFirmata in the Arduino-IDE under 'Examples->Firmata->StandardFirmata<br><br>
  1003. ConfigurableFirmata has to be installed manualy. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
  1004. ConfigurableFirmata</a> on GitHub or <a href="http://www.fhemwiki.de/wiki/Arduino_Firmata#Installation_ConfigurableFirmata">FHEM-Wiki</a><br>
  1005. </li>
  1006. <br>
  1007. <li>Network-connected devices:<br><br>
  1008. <code>&lt;port&gt;</code> specifies the port the FRM device listens on. If <code>global</code> is
  1009. specified the socket is bound to all local IP addresses, otherwise to localhost
  1010. only.<br><br>
  1011. The Arduino has to run either 'StandardFirmataEthernet' or 'ConfigurableFirmata'.
  1012. StandardFirmataEthernet supports Digital and Analog-I/O, Servo and I2C. In addition
  1013. to that ConfigurableFirmata supports 1-Wire and Stepper-motors.<br><br>
  1014. The connection is initiated by the Arduino in client-mode. Therefore the IP address and port
  1015. of the fhem-server has to be configured in the Arduino, so it knows where to connect to.<br>
  1016. As of now only a single Arduino per FRM-device configured is supported. Multiple
  1017. Arduinos may connect to different FRM-devices configured for different ports.<br><br>
  1018. You can find StandardFirmataEthernet in the Arduino-IDE under 'Examples->Firmata->StandardFirmataEthernet<br><br>
  1019. ConfigurableFirmata has to be installed manually. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
  1020. ConfigurableFirmata</a> on GitHub or <a href="http://www.fhemwiki.de/wiki/Arduino_Firmata#Installation_ConfigurableFirmata">FHEM-Wiki</a><br>
  1021. </li>
  1022. <br>
  1023. <li>
  1024. If the device is called none, then no device will be opened, so you
  1025. can experiment without hardware attached.<br>
  1026. </li>
  1027. </ul>
  1028. <br>
  1029. <a name="FRMset"></a>
  1030. <b>Set</b>
  1031. <ul>
  1032. <li>
  1033. <code>set &lt;name&gt; init</code><br>
  1034. reinitializes the FRM-Client-devices configured for this Arduino
  1035. </li><br>
  1036. <li>
  1037. <code>set &lt;name&gt; reset</code><br>
  1038. does a complete reset of FRM by disconnecting from, reconnecting to and reinitializing the Arduino and FRM internals and all attached FRM-client-devices
  1039. </li>
  1040. </ul>
  1041. <br><br>
  1042. <a name="FRMattr"></a>
  1043. <b>Attributes</b><br>
  1044. <ul>
  1045. <li>i2c-config<br>
  1046. Configure the Arduino for ic2 communication. This will enable i2c on the
  1047. i2c_pins received by the capability-query issued during initialization of FRM.<br>
  1048. As of Firmata 2.3 you can set a delay-time (in microseconds, max. 65535, default 0) that will be
  1049. inserted into i2c protocol when switching from write to read. This may be necessary because Firmata
  1050. i2c write does not block on the fhem side so consecutive i2c write/read operations get queued and
  1051. will be executed on the Firmata device in a different time sequence. Use the maximum operation
  1052. time required by the connected i2c devices (e.g. 30000 for the BMP180 with triple oversampling,
  1053. see i2c device manufacturer documentation for details). <br>
  1054. See: <a href="http://www.firmata.org/wiki/Protocol#I2C">Firmata Protocol details about I2C</a><br>
  1055. </li><br>
  1056. <li>sampling-interval<br>
  1057. Configure the interval Firmata reports analog data to FRM (in milliseconds, max. 65535). <br>
  1058. See: <a href="http://www.firmata.org/wiki/Protocol#Sampling_Interval">Firmata Protocol details about Sampling Interval</a></br>
  1059. </li>
  1060. </ul>
  1061. </ul>
  1062. <br>
  1063. =end html
  1064. =cut