44_S7_DWrite.pm 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. # $Id: 44_S7_DWrite.pm 15539 2017-12-01 21:52:13Z charlie71 $
  2. ##############################################
  3. package main;
  4. use strict;
  5. use warnings;
  6. use Time::HiRes qw(gettimeofday usleep);
  7. my %sets = (
  8. "on" => "",
  9. "off" => "",
  10. "toggle" => ""
  11. );
  12. my %gets = (
  13. "reading" => "",
  14. "STATE" => ""
  15. );
  16. sub __isfloat {
  17. my $val = shift;
  18. # return $val =~ m/^\d+.\d+$/;
  19. return $val =~ m/^[-+]?\d*\.?\d*$/;
  20. #[-+]?[0-9]*\.?[0-9]*
  21. }
  22. #####################################
  23. sub S7_DWrite_Initialize($) {
  24. my $hash = shift @_;
  25. # Provider
  26. # Consumer
  27. $hash->{Match} = "^DW";
  28. $hash->{DefFn} = "S7_DWrite_Define";
  29. $hash->{UndefFn} = "S7_DWrite_Undef";
  30. $hash->{SetFn} = "S7_DWrite_Set";
  31. $hash->{ParseFn} = "S7_DWrite_Parse";
  32. $hash->{AttrFn} = "S7_DWrite_Attr";
  33. $hash->{AttrList} = "IODev trigger_length " . $readingFnAttributes;
  34. main::LoadModule("S7");
  35. }
  36. #####################################
  37. sub S7_DWrite_Undef($$) {
  38. my ( $hash, $name ) = @_;
  39. RemoveInternalTimer($hash);
  40. Log3 $name, 4,
  41. "S7_DWrite ("
  42. . $hash->{IODev}{NAME}
  43. . "): undef "
  44. . $hash->{NAME}
  45. . " Adress:"
  46. . $hash->{ADDRESS};
  47. delete( $modules{S7_DWrite}{defptr} );
  48. return undef;
  49. }
  50. #####################################
  51. sub S7_DWrite_Define($$) {
  52. my ( $hash, $def ) = @_;
  53. my @a = split( "[ \t][ \t]*", $def );
  54. my ( $name, $area, $DB, $position );
  55. my $byte;
  56. my $bit;
  57. $name = $a[0];
  58. Log3 $name, 5, "S7_DWrite_Define called";
  59. AssignIoPort($hash); # logisches modul an physikalisches binden !!!
  60. my $sname = $hash->{IODev}{NAME};
  61. if ( uc $a[2] =~ m/^[QIMN](\d*)/ ) {
  62. $area = "db";
  63. $DB = 0;
  64. my $startposition;
  65. my $Offset;
  66. if ( uc $a[2] =~ m/^Q(\d*)/ ) {
  67. $startposition = 1;
  68. if ( $hash->{IODev}{S7TYPE} eq "LOGO7" ) {
  69. $Offset = 942;
  70. }
  71. elsif ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  72. $Offset = 1064;
  73. }
  74. else {
  75. my $msg =
  76. "wrong syntax : define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M|NI|NQ}1..24";
  77. Log3 undef, 2, $msg;
  78. return $msg;
  79. }
  80. }
  81. elsif ( uc $a[2] =~ m/^I(\d*)/ ) {
  82. $startposition = 1;
  83. if ( $hash->{IODev}{S7TYPE} eq "LOGO7" ) {
  84. $Offset = 923;
  85. }
  86. elsif ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  87. $Offset = 1024;
  88. }
  89. else {
  90. my $msg =
  91. "wrong syntax : define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M|NI|NQ}1..24";
  92. Log3 undef, 2, $msg;
  93. return $msg;
  94. }
  95. }
  96. elsif ( uc $a[2] =~ m/^NI(\d*)/ ) {
  97. $startposition = 2;
  98. if ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  99. $Offset = 1246;
  100. }
  101. else {
  102. my $msg =
  103. "wrong syntax : define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M|NI|NQ}1..24";
  104. Log3 undef, 2, $msg;
  105. return $msg;
  106. }
  107. }
  108. elsif ( uc $a[2] =~ m/^NQ(\d*)/ ) {
  109. $startposition = 2;
  110. if ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  111. $Offset = 1390;
  112. }
  113. else {
  114. my $msg =
  115. "wrong syntax : define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M|NI|NQ}1..24";
  116. Log3 undef, 2, $msg;
  117. return $msg;
  118. }
  119. }
  120. elsif ( uc $a[2] =~ m/^M(\d*)/ ) {
  121. $startposition = 1;
  122. if ( $hash->{IODev}{S7TYPE} eq "LOGO7" ) {
  123. $Offset = 948;
  124. }
  125. elsif ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  126. $Offset = 1104;
  127. }
  128. else {
  129. my $msg =
  130. "wrong syntax : define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M|NI|NQ}1..24";
  131. Log3 undef, 2, $msg;
  132. return $msg;
  133. }
  134. }
  135. else {
  136. my $msg =
  137. "wrong syntax : define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M|NI|NQ}1..24";
  138. Log3 undef, 2, $msg;
  139. return $msg;
  140. }
  141. $position =
  142. ( $Offset * 8 ) + int( substr( $a[2], $startposition ) ) - 1;
  143. $byte = int( $position / 8 );
  144. $bit = ( $position % 8 );
  145. }
  146. else {
  147. $area = lc $a[2];
  148. $DB = $a[3];
  149. $position = $a[4];
  150. if ( $area ne "inputs"
  151. && $area ne "outputs"
  152. && $area ne "flags"
  153. && $area ne "db" )
  154. {
  155. my $msg =
  156. "wrong syntax: define <name> S7_DWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_DWrite {I|Q|M}1..24";
  157. Log3 undef, 2, $msg;
  158. return $msg;
  159. }
  160. my @address = split( /\./, $position );
  161. if ( int(@address) == 2 ) {
  162. $byte = $address[0];
  163. $bit = $address[1];
  164. }
  165. else {
  166. $byte = int( $address[0] / 8 );
  167. $bit = ( $address[0] % 8 );
  168. }
  169. $position = ( $byte * 8 ) + $bit;
  170. }
  171. Log3 $name, 5, "S7_DWrite_Define called2";
  172. $hash->{ADDRESS} = "$byte.$bit";
  173. $hash->{AREA} = $area;
  174. $hash->{DB} = $DB;
  175. $hash->{LENGTH} = 1;
  176. $hash->{POSITION} = $position;
  177. my $ID = "$area $DB";
  178. if ( !defined( $modules{S7_DWrite}{defptr}{$ID} ) ) {
  179. my @b = ();
  180. push( @b, $hash );
  181. $modules{S7_DWrite}{defptr}{$ID} = \@b;
  182. }
  183. else {
  184. push( @{ $modules{S7_DWrite}{defptr}{$ID} }, $hash );
  185. }
  186. $hash->{IODev}{dirty} = 1;
  187. return undef;
  188. }
  189. #####################################
  190. sub S7_DWrite_setABit($$) {
  191. my ( $hash, $newValue ) = @_;
  192. my $name = $hash->{NAME};
  193. $newValue = lc $newValue;
  194. Log3 $name, 4, "S7_DWrite_setABit $newValue";
  195. if ( $newValue ne "on" && $newValue ne "off" && $newValue ne "trigger" ) {
  196. return "Unknown argument $newValue, choose one of ON OFF TRIGGER";
  197. }
  198. my $sname = $hash->{IODev}{NAME};
  199. my $position = $hash->{POSITION};
  200. my $area = $hash->{AREA};
  201. my $dbNR = $hash->{DB};
  202. my $shash = $defs{$sname};
  203. my $writeAreaIndex = S7_getAreaIndex4AreaName($area);
  204. return $writeAreaIndex if ( $writeAreaIndex ne int($writeAreaIndex) );
  205. my $b = 0;
  206. my $res;
  207. if ( $newValue eq "on" || $newValue eq "trigger" ) {
  208. $b = 1;
  209. }
  210. my $byte;
  211. my $bit;
  212. my $readbuffer;
  213. my @cbuffer;
  214. my $tbuffer;
  215. if ( $shash->{S7TYPE} eq "S5" ) {
  216. #S5
  217. #lesen wir das aktuelle byte
  218. $byte = int( $position / 8 );
  219. $bit = int( $position % 8 );
  220. ( $res, $readbuffer ) =
  221. S7_ReadBlockFromPLC( $shash, $writeAreaIndex, $dbNR, $byte, 1 );
  222. if ( $res == 0 && length($readbuffer) == 1 ) { #reading was OK
  223. #setzen/löschen wir das gewünsche bit
  224. $tbuffer = join( ", ", unpack( "H2 " x length($readbuffer), $readbuffer ) );
  225. Log3( undef, 5, "S5 Read old Value <-- " . $tbuffer ." now changing bitNr: ".$bit );
  226. @cbuffer = unpack( "C" x length($readbuffer), $readbuffer);
  227. if ($b == 1) {
  228. $cbuffer[0] |= (1 << $bit);
  229. } else {
  230. $cbuffer[0] &= (~(1 << $bit)) & 0xFF;
  231. }
  232. $readbuffer = pack( "C" x 1, @cbuffer);
  233. #schreiben wir das byte
  234. $tbuffer = join( ", ", unpack( "H2 " x length($readbuffer), $readbuffer ) );
  235. Log3( undef, 5, "S5 Write new Value <-- " . $tbuffer );
  236. $res = S7_WriteToPLC( $shash, $writeAreaIndex, $dbNR, $byte, &S7Client::S7WLByte , $readbuffer );
  237. if ( $res != 0 ) {
  238. my $error = $shash->{S7PLCClient}->getErrorStr($res);
  239. my $msg =
  240. "$name S7_DWrite_setABit -S5- S7_WriteToPLC error: $res=$error";
  241. Log3( $name, 3, $msg );
  242. }
  243. } else {
  244. my $error = $shash->{S7PLCClient}->getErrorStr($res);
  245. my $msg =
  246. "$name S7_DWrite_setABit -S5- ReadArea error: $res=$error";
  247. Log3( $name, 3, $msg );
  248. S7_reconnect($shash); #lets try a reconnect
  249. return ( -2, $msg );
  250. }
  251. } else {
  252. #S7
  253. $res = S7_WriteBitToPLC( $shash, $writeAreaIndex, $dbNR, $position, $b );
  254. }
  255. if ( $newValue eq "trigger" ) {
  256. my $triggerLength = 1;#1 second
  257. if ( defined( $main::attr{$name}{trigger_length} ) ) {
  258. $triggerLength = $main::attr{$name}{trigger_length};
  259. }
  260. if ($triggerLength >=1 ) {
  261. InternalTimer( gettimeofday() + $triggerLength, "S7_DWrite_SwitchOff", $hash, 1 );
  262. } else {
  263. #we use usleep
  264. $triggerLength = $triggerLength*1000*1000;
  265. $triggerLength = int($triggerLength);
  266. usleep ($triggerLength);
  267. if ( $shash->{S7TYPE} eq "S5" ) {
  268. $cbuffer[0] &= (~(1 << $bit)) & 0xFF;
  269. $readbuffer = pack( "C" x 1, @cbuffer);
  270. #schreiben wir das byte
  271. $tbuffer = join( ", ", unpack( "H2 " x length($readbuffer), $readbuffer ) );
  272. Log3( undef, 5, "S5 Write new Value 2 <-- " . $tbuffer );
  273. $res = S7_WriteToPLC( $shash, $writeAreaIndex, $dbNR, $byte, &S7Client::S7WLByte , $readbuffer );
  274. if ( $res != 0 ) {
  275. my $error = $shash->{S7PLCClient}->getErrorStr($res);
  276. my $msg =
  277. "$name S7_DWrite_setABit -S5- S7_WriteToPLC2 error: $res=$error";
  278. Log3( $name, 3, $msg );
  279. }
  280. } else {
  281. #S7
  282. $res =
  283. S7_WriteBitToPLC( $shash, $writeAreaIndex, $dbNR, $position, 0 );
  284. }
  285. $newValue = "off";
  286. }
  287. }
  288. if ( $res == 0 ) {
  289. main::readingsSingleUpdate( $hash, "state", $newValue, 1 );
  290. } else {
  291. main::readingsSingleUpdate( $hash, "state", "", 1 );
  292. }
  293. return undef;
  294. }
  295. #####################################
  296. sub S7_DWrite_Set(@) {
  297. my ( $hash, @a ) = @_;
  298. return "Need at least one parameter" if ( int(@a) < 2 );
  299. return S7_DWrite_setABit( $hash, $a[1] );
  300. }
  301. #####################################
  302. sub S7_DWrite_SwitchOff($) {
  303. my ($hash) = @_;
  304. my $name = $hash->{NAME};
  305. Log3 $name, 4, "S7_DWrite: GetUpdate called ...";
  306. return S7_DWrite_setABit( $hash, "off" );
  307. }
  308. #####################################
  309. sub S7_DWrite_Parse($$) {
  310. my ( $hash, $rmsg ) = @_;
  311. my $name;
  312. if ( defined( $hash->{NAME} ) ) {
  313. $name = $hash->{NAME};
  314. }
  315. else {
  316. $name = "dummy";
  317. Log3 undef, 2, "S7_DWrite_Parse: Error ...";
  318. return undef;
  319. }
  320. my @a = split( "[ \t][ \t]*", $rmsg );
  321. my @list;
  322. my ( $area, $DB, $start, $length, $datatype, $s7name, $hexbuffer,
  323. $clientNames );
  324. $area = lc $a[1];
  325. $DB = $a[2];
  326. $start = $a[3];
  327. $length = $a[4];
  328. $s7name = $a[5];
  329. $hexbuffer = $a[6];
  330. $clientNames = $a[7];
  331. my $ID = "$area $DB";
  332. Log3 $name, 6, "$name S7_DWrite_Parse $rmsg";
  333. my @clientList = split( ",", $clientNames );
  334. if ( int(@clientList) > 0 ) {
  335. my @Writebuffer = unpack( "C" x $length,
  336. pack( "H2" x $length, split( ",", $hexbuffer ) ) );
  337. my $now = gettimeofday();
  338. foreach my $clientName (@clientList) {
  339. my $h = $defs{$clientName};
  340. if ( $h->{TYPE} eq "S7_DWrite"
  341. && $start <= int( $h->{POSITION} / 8 )
  342. && $start + $length >= int( $h->{POSITION} / 8 ) )
  343. {
  344. push( @list, $clientName )
  345. ; #damit die werte im client gesetzt werden!
  346. #aktualisierung des wertes
  347. my $s = int( $h->{POSITION} / 8 ) - $start;
  348. my $myI = $hash->{S7PLCClient}->ByteAt( \@Writebuffer, $s );
  349. Log3 $name, 5, "$name S7_DWrite_Parse update $clientName ";
  350. # if ( ( int($myI) & ( 1 << ( $h->{POSITION} % 8 ) ) ) > 0 ) {
  351. # main::readingsSingleUpdate( $h, "state", "on", 1 );
  352. # }
  353. # else {
  354. # main::readingsSingleUpdate( $h, "state", "off", 1 );
  355. # }
  356. my $valueText = "";
  357. my $reading="state";
  358. if ( ( int($myI) & ( 1 << ( $h->{POSITION} % 8 ) ) ) > 0 ) {
  359. $valueText = "on";
  360. }
  361. else {
  362. $valueText = "off";
  363. }
  364. #check event-onchange-reading
  365. #code wurde der datei fhem.pl funktion readingsBulkUpdate entnommen und adaptiert
  366. my $attreocr= AttrVal($h->{NAME}, "event-on-change-reading", undef);
  367. my @a;
  368. if($attreocr) {
  369. @a = split(/,/,$attreocr);
  370. $h->{".attreocr"} = \@a;
  371. }
  372. # determine whether the reading is listed in any of the attributes
  373. my @eocrv;
  374. my $eocr = $attreocr &&
  375. ( @eocrv = grep { my $l = $_; $l =~ s/:.*//;
  376. ($reading=~ m/^$l$/) ? $_ : undef} @a);
  377. # check if threshold is given
  378. my $eocrExists = $eocr;
  379. if( $eocr
  380. && $eocrv[0] =~ m/.*:(.*)/ ) {
  381. my $threshold = $1;
  382. if($valueText =~ m/([\d\.\-eE]+)/ && looks_like_number($1)) { #41083, #62190
  383. my $mv = $1;
  384. my $last_value = $h->{".attreocr-threshold$reading"};
  385. if( !defined($last_value) ) {
  386. # $h->{".attreocr-threshold$reading"} = $mv;
  387. } elsif( abs($mv - $last_value) < $threshold ) {
  388. $eocr = 0;
  389. } else {
  390. # $h->{".attreocr-threshold$reading"} = $mv;
  391. }
  392. }
  393. }
  394. my $changed = !($attreocr)
  395. || ($eocr && ($valueText ne ReadingsVal($h->{NAME},$reading,"")));
  396. my $attrminint = AttrVal($h->{NAME}, "event-min-interval", undef);
  397. my @aa;
  398. if($attrminint) {
  399. @aa = split(/,/,$attrminint);
  400. }
  401. my @v = grep { my $l = $_;
  402. $l =~ s/:.*//;
  403. ($reading=~ m/^$l$/) ? $_ : undef
  404. } @aa;
  405. if(@v) {
  406. my (undef, $minInt) = split(":", $v[0]);
  407. my $le = $h->{".lastTime$reading"};
  408. if($le && $now-$le < $minInt) {
  409. if(!$eocr || ($eocr && $valueText eq ReadingsVal($h->{NAME},$reading,""))){
  410. $changed = 0;
  411. #} else {
  412. # $hash->{".lastTime$reading"} = $now;
  413. }
  414. } else {
  415. #$hash->{".lastTime$reading"} = $now;
  416. $changed = 1 if($eocrExists);
  417. }
  418. }
  419. if ($changed == 1) {
  420. main::readingsSingleUpdate( $h, $reading, $valueText, 1 );
  421. }
  422. }
  423. }
  424. }
  425. else {
  426. Log3 $name, 3, "$name S7_DWrite_Parse going the save way ";
  427. if ( defined( $modules{S7_DWrite}{defptr}{$ID} ) ) {
  428. foreach my $h ( @{ $modules{S7_DWrite}{defptr}{$ID} } ) {
  429. if ( defined( $main::attr{ $h->{NAME} }{IODev} )
  430. && $main::attr{ $h->{NAME} }{IODev} eq $name )
  431. {
  432. if ( $start <= int( $h->{POSITION} / 8 )
  433. && $start + $length >= int( $h->{POSITION} / 8 ) )
  434. {
  435. my $n = $h
  436. ->{NAME}; #damit die werte im client gesetzt werden!
  437. push( @list, $n );
  438. #aktualisierung des wertes
  439. my @Writebuffer = unpack(
  440. "C" x $length,
  441. pack(
  442. "H2" x $length, split( ",", $hexbuffer )
  443. )
  444. );
  445. my $s = int( $h->{POSITION} / 8 ) - $start;
  446. # my $b = pack( "C" x $length, @Writebuffer );
  447. my $myI =
  448. $hash->{S7PLCClient}->ByteAt( \@Writebuffer, $s );
  449. Log3 $name, 6, "$name S7_DWrite_Parse update $n ";
  450. if ( ( int($myI) & ( 1 << ( $h->{POSITION} % 8 ) ) )
  451. > 0 )
  452. {
  453. main::readingsSingleUpdate( $h, "state", "on",
  454. 1 );
  455. }
  456. else {
  457. main::readingsSingleUpdate( $h, "state", "off",
  458. 1 );
  459. }
  460. }
  461. }
  462. }
  463. }
  464. }
  465. if ( int(@list) == 0 ) {
  466. Log3 $name, 6, "S7_DWrite: Parse no client found ($name) ...";
  467. push( @list, "" );
  468. }
  469. return @list;
  470. }
  471. #####################################
  472. sub S7_DWrite_Attr(@) {
  473. my ( $cmd, $name, $aName, $aVal ) = @_;
  474. # $cmd can be "del" or "set"
  475. # $name is device name
  476. # aName and aVal are Attribute name and value
  477. my $hash = $defs{$name};
  478. if ( $cmd eq "set" ) {
  479. if ( $aName eq "trigger_length" ) {
  480. if ( !__isfloat ($aVal) ) {
  481. Log3 $name, 3,
  482. "S7_DWrite: Invalid $aName in attr $name $aName ($aVal is not a number): $@";
  483. return "Invalid $aName : $aVal is not a number";
  484. }
  485. }
  486. elsif ( $aName eq "IODev" ) {
  487. Log3 $name, 4, "S7_DWrite: IODev for $name is $aVal";
  488. $hash->{IODev}{dirty} = 1;
  489. }
  490. }
  491. return undef;
  492. }
  493. 1;
  494. =pod
  495. =item summary logical device for a digital writing to a S7/S5
  496. =item summary_DE logisches Device für einen binären Lese/Schreib Datenpunkt zu einer S5 / S7
  497. =begin html
  498. <p><a name="S7_DWrite"></a></p>
  499. <h3>S7_DWrite</h3>
  500. <ul>
  501. <ul>This module is a logical module of the physical module S7.</ul>
  502. </ul>
  503. <ul>
  504. <ul>This module is used to set/unset a Bit in ad DB of the PLC.</ul>
  505. </ul>
  506. <ul>
  507. <ul>Note: you have to configure a PLC writing at the physical modul (S7) first.</ul>
  508. </ul>
  509. <p><br /><br /><br /><strong>Define</strong><code>define &lt;name&gt; S7_DWrite {db} &lt;DB&gt; &lt;address&gt;</code></p>
  510. <ul>
  511. <ul>
  512. <ul>
  513. <ul>
  514. <li>db &hellip; defines where to read. Note currently only writing in to DB are supported.</li>
  515. <li>DB &hellip; Number of the DB</li>
  516. <li>address &hellip; address you want to write. bit number to read. Example: 10.6</li>
  517. </ul>
  518. Note: the required memory area need to be with in the configured PLC reading of the physical module.</ul>
  519. </ul>
  520. </ul>
  521. <p><strong>Set</strong><code>set &lt;name&gt; S7_AWrite {ON|OFF|TRIGGER};</code></p>
  522. <ul>
  523. <ul>Note: TRIGGER sets the bit for 1s to ON than it will set to OFF.</ul>
  524. </ul>
  525. <p><strong>Attr</strong><br /> The following parameters are used to scale every reading</p>
  526. <ul>
  527. <li>trigger_length ... sets the on-time of a trigger in Seconds. Note out can also use trigger_length less than 1</li>
  528. </ul>
  529. =end html
  530. =begin html_DE
  531. <p><a name="S7_DWrite"></a></p>
  532. <h3>S7_DWrite</h3>
  533. <ul>
  534. <ul>This module is a logical module of the physical module S7.</ul>
  535. </ul>
  536. <ul>
  537. <ul>This module is used to set/unset a Bit in ad DB of the PLC.</ul>
  538. </ul>
  539. <ul>
  540. <ul>Note: you have to configure a PLC writing at the physical modul (S7) first.</ul>
  541. </ul>
  542. <p><br /><br /><br /><strong>Define</strong><code>define &lt;name&gt; S7_DWrite {db} &lt;DB&gt; &lt;position&gt;</code></p>
  543. <ul>
  544. <ul>
  545. <ul>
  546. <ul>
  547. <li>db &hellip; defines where to read. Note currently only writing in to DB are supported.</li>
  548. <li>DB &hellip; Number of the DB</li>
  549. <li>address &hellip; address you want to write. bit number to read. Example: 10.6</li>
  550. </ul>
  551. Note: the required memory area need to be with in the configured PLC reading of the physical module.</ul>
  552. </ul>
  553. </ul>
  554. <p><br /><strong>Set</strong><code>set &lt;name&gt; S7_AWrite {ON|OFF|TRIGGER};</code></p>
  555. <ul>
  556. <ul>Note: TRIGGER sets the bit for 1s to ON than it will set to OFF.</ul>
  557. </ul>
  558. <p><strong>Attr</strong><br /> The following parameters are used to scale every reading</p>
  559. <ul>
  560. <li>trigger_length ... sets the on-time of a trigger in Seconds. Note out can also use trigger_length less than 1</li>
  561. </ul>
  562. =end html_DE
  563. =cut