44_S7_AWrite.pm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. # $Id: 44_S7_AWrite.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);
  7. require "44_S7_Client.pm";
  8. my %gets = (
  9. "reading" => "",
  10. "STATE" => ""
  11. );
  12. #####################################
  13. sub S7_AWrite_Initialize($) {
  14. my $hash = shift @_;
  15. # Consumer
  16. $hash->{Match} = "^AW";
  17. $hash->{DefFn} = "S7_AWrite_Define";
  18. $hash->{UndefFn} = "S7_AWrite_Undef";
  19. # $hash->{GetFn} = "S7_AWrite_Get";
  20. $hash->{SetFn} = "S7_AWrite_Set";
  21. $hash->{ParseFn} = "S7_AWrite_Parse";
  22. $hash->{AttrFn} = "S7_AWrite_Attr";
  23. $hash->{AttrList} = "IODev " . $readingFnAttributes;
  24. main::LoadModule("S7");
  25. }
  26. #####################################
  27. sub S7_AWrite_Define($$) {
  28. my ( $hash, $def ) = @_;
  29. my @a = split( "[ \t][ \t]*", $def );
  30. my ( $name, $area, $DB, $start, $datatype, $length );
  31. $name = $a[0];
  32. AssignIoPort($hash);
  33. if ( uc $a[2] =~ m/^[NA](\d*)/ ) {
  34. my $Offset;
  35. $area = "db";
  36. $DB = 0;
  37. my $startposition;
  38. if ( uc $a[2] =~ m/^AI(\d*)/ ) {
  39. $startposition = 2;
  40. if ( defined($hash->{IODev}{S7TYPE}) && $hash->{IODev}{S7TYPE} eq "LOGO7" ) {
  41. $Offset = 926;
  42. }
  43. elsif ( defined($hash->{IODev}{S7TYPE}) && $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  44. $Offset = 1032;
  45. }
  46. else {
  47. my $msg =
  48. "wrong syntax : define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  49. Log3 undef, 2, $msg;
  50. return $msg;
  51. }
  52. }
  53. elsif ( uc $a[2] =~ m/^AQ(\d*)/ ) {
  54. $startposition = 2;
  55. if ( defined($hash->{IODev}{S7TYPE}) && $hash->{IODev}{S7TYPE} eq "LOGO7" ) {
  56. $Offset = 944;
  57. }
  58. elsif ( defined($hash->{IODev}{S7TYPE}) && $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  59. $Offset = 1072;
  60. }
  61. else {
  62. my $msg =
  63. "wrong syntax : define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  64. Log3 undef, 2, $msg;
  65. return $msg;
  66. }
  67. }
  68. elsif ( uc $a[2] =~ m/^AM(\d*)/ ) {
  69. $startposition = 2;
  70. if ( defined($hash->{IODev}{S7TYPE}) && $hash->{IODev}{S7TYPE} eq "LOGO7" ) {
  71. $Offset = 952;
  72. }
  73. elsif ( defined($hash->{IODev}{S7TYPE}) && $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  74. $Offset = 1118;
  75. }
  76. else {
  77. my $msg =
  78. "wrong syntax : define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  79. Log3 undef, 2, $msg;
  80. return $msg;
  81. }
  82. }
  83. elsif ( uc $a[2] =~ m/^NAI(\d*)/ ) {
  84. $startposition = 3;
  85. if ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  86. $Offset = 1262;
  87. }
  88. else {
  89. my $msg =
  90. "wrong syntax : define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  91. Log3 undef, 2, $msg;
  92. return $msg;
  93. }
  94. }
  95. elsif ( uc $a[2] =~ m/^NAQ(\d*)/ ) {
  96. $startposition = 3;
  97. if ( $hash->{IODev}{S7TYPE} eq "LOGO8" ) {
  98. $Offset = 1406;
  99. }
  100. else {
  101. my $msg =
  102. "wrong syntax : define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  103. Log3 undef, 2, $msg;
  104. return $msg;
  105. }
  106. }
  107. else {
  108. my $msg =
  109. "wrong syntax : define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <address> \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  110. Log3 undef, 2, $msg;
  111. return $msg;
  112. }
  113. $start = $Offset + ((int( substr( $a[2], $startposition ) ) - 1)*2);
  114. $datatype = "u16";
  115. }
  116. else {
  117. $area = lc $a[2];
  118. $DB = $a[3];
  119. $start = $a[4];
  120. $datatype = lc $a[5];
  121. Log3 $name, 5, "$name S7_AWrite_Define called";
  122. if ( $area ne "inputs"
  123. && $area ne "outputs"
  124. && $area ne "flags"
  125. && $area ne "db" )
  126. {
  127. my $msg =
  128. "$name wrong syntax: define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <start> {u8|s8|u16|s16|u32|s32|float} \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  129. Log3 $name, 2, $msg;
  130. return $msg;
  131. }
  132. if ( $datatype ne "u8"
  133. && $datatype ne "s8"
  134. && $datatype ne "u16"
  135. && $datatype ne "s16"
  136. && $datatype ne "u32"
  137. && $datatype ne "s32"
  138. && $datatype ne "float" )
  139. {
  140. my $msg =
  141. "$name wrong syntax: define <name> S7_AWrite {inputs|outputs|flags|db} <DB> <start> {u8|s8|u16|s16|u32|s32|float} \n Only for Logo7 or Logo8:\n define <name> S7_AWrite {AI|AM|AQ|NAI|NAQ}";
  142. Log3 $name, 2, $msg;
  143. return $msg;
  144. }
  145. my $sname = $hash->{IODev}{NAME};
  146. if ( $datatype eq "u16" || $datatype eq "s16" ) {
  147. $length = 2;
  148. }
  149. elsif ( $datatype eq "u32" || $datatype eq "s32" || $datatype eq "float" ) {
  150. $length = 4;
  151. }
  152. else {
  153. $length = 1;
  154. }
  155. }
  156. $hash->{AREA} = $area;
  157. $hash->{DB} = $DB;
  158. $hash->{ADDRESS} = $start;
  159. $hash->{DATATYPE} = $datatype;
  160. $hash->{LENGTH} = $length;
  161. my $ID = "$area $DB";
  162. if ( !defined( $modules{S7_AWrite}{defptr}{$ID} ) ) {
  163. my @b = ();
  164. push( @b, $hash );
  165. $modules{S7_AWrite}{defptr}{$ID} = \@b;
  166. }
  167. else {
  168. push( @{ $modules{S7_AWrite}{defptr}{$ID} }, $hash );
  169. }
  170. Log3 $name, 4,
  171. "S7_AWrite (" . $hash->{IODev}{NAME} . "): define $name Adress:$start";
  172. $hash->{IODev}{dirty} = 1;
  173. return undef;
  174. }
  175. #####################################
  176. sub S7_AWrite_Undef($$) {
  177. my ( $hash, $name ) = @_;
  178. Log3 $name, 4,
  179. "S7_AWrite ("
  180. . $hash->{IODev}{NAME}
  181. . "): undef "
  182. . $hash->{NAME}
  183. . " Adress:"
  184. . $hash->{ADDRESS};
  185. delete( $modules{S7_AWrite}{defptr} );
  186. return undef;
  187. }
  188. #####################################
  189. sub S7_AWrite_Set($@) {
  190. my ( $hash, @a ) = @_;
  191. my $name = $hash->{NAME};
  192. Log3 $name, 5, "$name S7_AWrite_Set";
  193. my $minValue;
  194. my $maxValue;
  195. my $datatype = $hash->{DATATYPE};
  196. #note I have used a SIEMENS Logo for testing here just the following range was supported.
  197. # $minValue = 0;
  198. # $maxValue = 32767;
  199. if ( $datatype eq "u16" ) {
  200. $minValue = 0;
  201. $maxValue = 65535;
  202. }
  203. elsif ( $datatype eq "s16" ) {
  204. $minValue = -32768;
  205. $maxValue = 32767;
  206. }
  207. elsif ( $datatype eq "u32" ) {
  208. $minValue = 0;
  209. $maxValue = 4294967295;
  210. }
  211. elsif ( $datatype eq "s32" ) {
  212. $minValue = -2147483648;
  213. $maxValue = 2147483647;
  214. }
  215. elsif ( $datatype eq "float" ) {
  216. $minValue = -3.402823e38;
  217. $maxValue = 3.402823e38;
  218. }
  219. elsif ( $datatype eq "u8" ) {
  220. $minValue = 0;
  221. $maxValue = 255;
  222. }
  223. elsif ( $datatype eq "s8" ) {
  224. $minValue = -128;
  225. $maxValue = 127;
  226. }
  227. else { #should never happen
  228. $minValue = -1;
  229. $maxValue = 0;
  230. }
  231. return "$name Need at least one parameter" if ( int(@a) < 2 );
  232. return " : " if ( $a[1] eq "?" );
  233. if ( $a[1] ne int( $a[1] ) && $datatype ne "float" ) {
  234. return "$name You have to enter a numeric value: $minValue - $maxValue";
  235. }
  236. my $newValue;
  237. if ( $datatype ne "float" ) {
  238. $newValue = int( $a[1] );
  239. }
  240. else {
  241. $newValue = $a[1];
  242. }
  243. if ( $newValue < $minValue || $newValue > $maxValue ) {
  244. return "$name Out of range: $minValue - $maxValue";
  245. }
  246. my $sname = $hash->{IODev}{NAME};
  247. #find the rigth config
  248. my $area = $hash->{AREA};
  249. my $length = $hash->{LENGTH};
  250. my $start = $hash->{ADDRESS};
  251. my $dbNR = $hash->{DB};
  252. my $shash = $defs{$sname};
  253. if ( !defined( $shash->{S7PLCClient} ) ) {
  254. my $err = "$name S7_AWrite_Set: not connected to PLC ";
  255. Log3 $name, 3, $err;
  256. return $err;
  257. }
  258. if ( $shash->{STATE} ne "connected to PLC" ) {
  259. my $err = "$name S7_AWrite_Set: not connected to PLC";
  260. Log3 $name, 3, $err;
  261. return $err;
  262. }
  263. my $b;
  264. my $WordLen;
  265. if ( $datatype eq "u8" ) {
  266. $b = $shash->{S7PLCClient}->setByteAt( "X", 0, $newValue );
  267. $WordLen = &S7Client::S7WLByte;
  268. }
  269. elsif ( $datatype eq "s8" ) {
  270. $b = $shash->{S7PLCClient}->setShortAt( "X", 0, $newValue );
  271. $WordLen = &S7Client::S7WLByte;
  272. }
  273. elsif ( $datatype eq "u16" ) {
  274. $b = $shash->{S7PLCClient}->setWordAt( "XX", 0, $newValue );
  275. $WordLen = &S7Client::S7WLInt;
  276. # $WordLen = &S7Client::S7WLWord;
  277. }
  278. elsif ( $datatype eq "s16" ) {
  279. $b = $shash->{S7PLCClient}->setIntegerAt( "XX", 0, $newValue );
  280. $WordLen = &S7Client::S7WLInt;
  281. # $WordLen = &S7Client::S7WLWord;
  282. }
  283. elsif ( $datatype eq "u32" ) {
  284. $b = $shash->{S7PLCClient}->setDWordAt( "XXXX", 0, $newValue );
  285. $WordLen = &S7Client::S7WLDInt;
  286. # $WordLen = &S7Client::S7WLDWord;
  287. }
  288. elsif ( $datatype eq "s32" ) {
  289. $b = $shash->{S7PLCClient}->setDintAt( "XXXX", 0, $newValue );
  290. $WordLen = &S7Client::S7WLDInt;
  291. # $WordLen = &S7Client::S7WLDWord;
  292. }
  293. elsif ( $datatype eq "float" ) {
  294. $b = $shash->{S7PLCClient}->setFloatAt( "XXXX", 0, $newValue );
  295. $WordLen = &S7Client::S7WLReal;
  296. }
  297. else {
  298. my $err = "$name S7_AWrite: Parse unknown type : (" . $datatype . ")";
  299. Log3 $name, 3, $err;
  300. return $err;
  301. }
  302. my $bss = join( ", ", unpack( "H2" x $length, $b ) );
  303. Log3 $name, 5, "$name S7_AWrite_Set: Write Bytes to PLC: $bss";
  304. my $writeAreaIndex = S7_getAreaIndex4AreaName($area);
  305. return $writeAreaIndex if ( $writeAreaIndex ne int($writeAreaIndex) );
  306. # my $res = S7_WriteBlockToPLC($shash,$writeAreaIndex,$dbNR,$start,$b);
  307. my $res =
  308. S7_WriteToPLC( $shash, $writeAreaIndex, $dbNR, $start, $WordLen, $b );
  309. if ( $res == 0 ) {
  310. main::readingsSingleUpdate( $hash, "state", $newValue, 1 );
  311. }
  312. else {
  313. main::readingsSingleUpdate( $hash, "state", "", 1 );
  314. }
  315. return undef;
  316. }
  317. #####################################
  318. sub S7_AWrite_Parse($$) {
  319. my ( $hash, $rmsg ) = @_;
  320. my $name = $hash->{NAME};
  321. my @list;
  322. my @a = split( "[ \t][ \t]*", $rmsg );
  323. my ( $area, $DB, $start, $length, $datatype, $s7name, $hexbuffer,
  324. $clientNames );
  325. $area = lc $a[1];
  326. $DB = $a[2];
  327. $start = $a[3];
  328. $length = $a[4];
  329. $s7name = $a[5];
  330. $hexbuffer = $a[6];
  331. $clientNames = $a[7];
  332. my $ID = "$area $DB";
  333. Log3 $name, 5, "$name S7_AWrite_Parse $rmsg";
  334. my @clientList = split( ",", $clientNames );
  335. if ( int(@clientList) > 0 ) {
  336. my @Writebuffer = unpack( "C" x $length,
  337. pack( "H2" x $length, split( ",", $hexbuffer ) ) );
  338. #my $b = pack( "C" x $length, @Writebuffer );
  339. my $now = gettimeofday();
  340. foreach my $clientName (@clientList) {
  341. my $h = $defs{$clientName};
  342. if ( $h->{TYPE} eq "S7_AWrite"
  343. && $start <= $h->{ADDRESS}
  344. && $start + $length >= $h->{ADDRESS} + $h->{LENGTH} )
  345. {
  346. my $n = $h->{NAME}; #damit die werte im client gesetzt werden!
  347. push( @list, $n );
  348. #Aktualisierung des wertes
  349. my $s = $h->{ADDRESS} - $start;
  350. my $myI;
  351. if ( $h->{DATATYPE} eq "u8" ) {
  352. $myI = $hash->{S7PLCClient}->ByteAt( \@Writebuffer, $s );
  353. }
  354. elsif ( $h->{DATATYPE} eq "s8" ) {
  355. $myI = $hash->{S7PLCClient}->ShortAt( \@Writebuffer, $s );
  356. }
  357. elsif ( $h->{DATATYPE} eq "u16" ) {
  358. $myI = $hash->{S7PLCClient}->WordAt( \@Writebuffer, $s );
  359. }
  360. elsif ( $h->{DATATYPE} eq "s16" ) {
  361. $myI = $hash->{S7PLCClient}->IntegerAt( \@Writebuffer, $s );
  362. }
  363. elsif ( $h->{DATATYPE} eq "u32" ) {
  364. $myI = $hash->{S7PLCClient}->DWordAt( \@Writebuffer, $s );
  365. }
  366. elsif ( $h->{DATATYPE} eq "s32" ) {
  367. $myI = $hash->{S7PLCClient}->DintAt( \@Writebuffer, $s );
  368. }
  369. elsif ( $h->{DATATYPE} eq "float" ) {
  370. $myI = $hash->{S7PLCClient}->FloatAt( \@Writebuffer, $s );
  371. }
  372. else {
  373. Log3 $name, 3, "$name S7_AWrite: Parse unknown type : ("
  374. . $h->{DATATYPE} . ")";
  375. }
  376. #main::readingsSingleUpdate( $h, "state", $myI, 1 );
  377. my $reading="state";
  378. #check event-onchange-reading
  379. #code wurde der datei fhem.pl funktion readingsBulkUpdate entnommen und adaptiert
  380. my $attreocr= AttrVal($h->{NAME}, "event-on-change-reading", undef);
  381. my @a;
  382. if($attreocr) {
  383. @a = split(/,/,$attreocr);
  384. $h->{".attreocr"} = \@a;
  385. }
  386. # determine whether the reading is listed in any of the attributes
  387. my @eocrv;
  388. my $eocr = $attreocr &&
  389. ( @eocrv = grep { my $l = $_; $l =~ s/:.*//;
  390. ($reading=~ m/^$l$/) ? $_ : undef} @a);
  391. # check if threshold is given
  392. my $eocrExists = $eocr;
  393. if( $eocr
  394. && $eocrv[0] =~ m/.*:(.*)/ ) {
  395. my $threshold = $1;
  396. if($myI =~ m/([\d\.\-eE]+)/ && looks_like_number($1)) { #41083, #62190
  397. my $mv = $1;
  398. my $last_value = $h->{".attreocr-threshold$reading"};
  399. if( !defined($last_value) ) {
  400. # $h->{".attreocr-threshold$reading"} = $mv;
  401. } elsif( abs($mv - $last_value) < $threshold ) {
  402. $eocr = 0;
  403. } else {
  404. # $h->{".attreocr-threshold$reading"} = $mv;
  405. }
  406. }
  407. }
  408. my $changed = !($attreocr)
  409. || ($eocr && ($myI ne ReadingsVal($h->{NAME},$reading,"")));
  410. my $attrminint = AttrVal($h->{NAME}, "event-min-interval", undef);
  411. my @aa;
  412. if($attrminint) {
  413. @aa = split(/,/,$attrminint);
  414. }
  415. my @v = grep { my $l = $_;
  416. $l =~ s/:.*//;
  417. ($reading=~ m/^$l$/) ? $_ : undef
  418. } @aa;
  419. if(@v) {
  420. my (undef, $minInt) = split(":", $v[0]);
  421. my $le = $h->{".lastTime$reading"};
  422. if($le && $now-$le < $minInt) {
  423. if(!$eocr || ($eocr && $myI eq ReadingsVal($h->{NAME},$reading,""))){
  424. $changed = 0;
  425. #} else {
  426. # $hash->{".lastTime$reading"} = $now;
  427. }
  428. } else {
  429. #$hash->{".lastTime$reading"} = $now;
  430. $changed = 1 if($eocrExists);
  431. }
  432. }
  433. if ($changed == 1) {
  434. main::readingsSingleUpdate( $h, $reading, $myI, 1 );
  435. }
  436. }
  437. }
  438. }
  439. else {
  440. Log3 $name, 3, "$name S7_AWrite_Parse going the save way ";
  441. if ( defined( $modules{S7_AWrite}{defptr}{$ID} ) ) {
  442. foreach my $h ( @{ $modules{S7_AWrite}{defptr}{$ID} } ) {
  443. if ( defined( $main::attr{ $h->{NAME} }{IODev} )
  444. && $main::attr{ $h->{NAME} }{IODev} eq $name )
  445. {
  446. if ( $start <= $h->{ADDRESS}
  447. && $start + $length >= $h->{ADDRESS} + $h->{LENGTH} )
  448. {
  449. my $n =
  450. $h->{NAME}; #damit die werte im client gesetzt werden!
  451. push( @list, $n );
  452. #Aktualisierung des wertes
  453. my @Writebuffer = unpack( "C" x $length,
  454. pack( "H2" x $length, split( ",", $hexbuffer ) ) );
  455. my $s = $h->{ADDRESS} - $start;
  456. # my $b = pack( "C" x $length, @Writebuffer );
  457. my $myI;
  458. if ( $h->{DATATYPE} eq "u8" ) {
  459. $myI =
  460. $hash->{S7PLCClient}->ByteAt( \@Writebuffer, $s );
  461. }
  462. elsif ( $h->{DATATYPE} eq "s8" ) {
  463. $myI =
  464. $hash->{S7PLCClient}
  465. ->ShortAt( \@Writebuffer, $s );
  466. }
  467. elsif ( $h->{DATATYPE} eq "u16" ) {
  468. $myI =
  469. $hash->{S7PLCClient}->WordAt( \@Writebuffer, $s );
  470. }
  471. elsif ( $h->{DATATYPE} eq "s16" ) {
  472. $myI =
  473. $hash->{S7PLCClient}
  474. ->IntegerAt( \@Writebuffer, $s );
  475. }
  476. elsif ( $h->{DATATYPE} eq "u32" ) {
  477. $myI =
  478. $hash->{S7PLCClient}
  479. ->DWordAt( \@Writebuffer, $s );
  480. }
  481. elsif ( $h->{DATATYPE} eq "s32" ) {
  482. $myI =
  483. $hash->{S7PLCClient}->DintAt( \@Writebuffer, $s );
  484. }
  485. elsif ( $h->{DATATYPE} eq "float" ) {
  486. $myI =
  487. $hash->{S7PLCClient}
  488. ->FloatAt( \@Writebuffer, $s );
  489. }
  490. else {
  491. Log3 $name, 3,
  492. "$name S7_AWrite: Parse unknown type : ("
  493. . $h->{DATATYPE} . ")";
  494. }
  495. main::readingsSingleUpdate( $h, "state", $myI, 1 );
  496. }
  497. }
  498. }
  499. }
  500. }
  501. if ( int(@list) == 0 ) {
  502. Log3 $name, 5, "S7_AWrite: Parse no client found ($name) ...";
  503. push( @list, "" );
  504. # return undef;
  505. }
  506. return @list;
  507. }
  508. #####################################
  509. sub S7_AWrite_Attr(@) {
  510. my ( $cmd, $name, $aName, $aVal ) = @_;
  511. # $cmd can be "del" or "set"
  512. # $name is device name
  513. # aName and aVal are Attribute name and value
  514. my $hash = $defs{$name};
  515. if ( $cmd eq "set" ) {
  516. if ( $aName eq "IODev" ) {
  517. if ( defined( $hash->{IODev} ) ) { #set old master device dirty
  518. $hash->{IODev}{dirty} = 1;
  519. }
  520. if ( defined( $defs{$aVal} ) ) { #set new master device dirty
  521. $defs{$aVal}{dirty} = 1;
  522. }
  523. Log3 $name, 4, "S7_AWrite: IODev for $name is $aVal";
  524. }
  525. }
  526. return undef;
  527. }
  528. 1;
  529. =pod
  530. =item summary logical device for a analog writing to a S7/S5
  531. =item summary_DE logisches Device für einen analogen Lese/Schreib Datenpunkt zu einer S5 / S7
  532. =begin html
  533. <p><a name="S7_AWrite"></a></p>
  534. <h3>S7_AWrite</h3>
  535. <ul>
  536. <ul>This module is a logical module of the physical module S7.</ul>
  537. </ul>
  538. <ul>
  539. <ul>This module provides sending analog data (unsigned integer Values) to the PLC.</ul>
  540. </ul>
  541. <ul>
  542. <ul>Note: you have to configure a PLC writing at the physical modul (S7) first.</ul>
  543. </ul>
  544. <p><br /><br /><strong>Define</strong><br /><code>define &lt;name&gt; S7_AWrite {inputs|outputs|flags|db} &lt;DB&gt; &lt;start&gt; {u8|s8|u16|s16|u32|s32|float}</code><br /><br /></p>
  545. <ul>
  546. <ul>
  547. <ul>
  548. <ul>
  549. <li>db &hellip; defines where to read. Note currently only writing in to DB are supported.</li>
  550. <li>DB &hellip; Number of the DB</li>
  551. <li>start &hellip; start byte of the reading</li>
  552. <li>{u8|s8|u16|s16|u32|s32} &hellip; defines the datatype:</li>
  553. <ul>
  554. <li>u8 &hellip;. unsigned 8 Bit integer</li>
  555. <li>s8 &hellip;. signed 8 Bit integer</li>
  556. <li>u16 &hellip;. unsigned 16 Bit integer</li>
  557. <li>s16 &hellip;. signed 16 Bit integer</li>
  558. <li>u32 &hellip;. unsigned 32 Bit integer</li>
  559. <li>s32 &hellip;. signed 32 Bit integer</li>
  560. <li>float &hellip;. 4 byte float</li>
  561. </ul>
  562. </ul>
  563. Note: the required memory area (start &ndash; start + datatypelength) need to be with in the configured PLC writing of the physical module.</ul>
  564. </ul>
  565. </ul>
  566. <p>Logo 7 / Logo 8</p>
  567. <p style="padding-left: 60px;">For Logo7 / Logo 8 also a short notation is supportet:</p>
  568. <p><code>define &lt;name&gt; S7_AWrite {AI|AM|AQ|NAI|NAQ}X</code></p>
  569. <p><strong>Set</strong><br /><br /><code>set &lt;name&gt; S7_AWrite &lt;value&gt;</code></p>
  570. <ul>
  571. <ul>
  572. <ul>
  573. <li>value &hellip; an numeric value</li>
  574. </ul>
  575. </ul>
  576. </ul>
  577. =end html
  578. =begin html_DE
  579. <p><a name="S7_AWrite"></a></p>
  580. <h3>S7_AWrite</h3>
  581. <ul>
  582. <ul>This module is a logical module of the physical module S7.</ul>
  583. </ul>
  584. <ul>
  585. <ul>This module provides sending analog data (unsigned integer Values) to the PLC.</ul>
  586. </ul>
  587. <ul>
  588. <ul>Note: you have to configure a PLC writing at the physical modul (S7) first.</ul>
  589. </ul>
  590. <p><br /><br /><strong>Define</strong><br /><code>define &lt;name&gt; S7_AWrite {inputs|outputs|flags|db} &lt;DB&gt; &lt;start&gt; {u8|s8|u16|s16|u32|s32|float}</code><br /><br /></p>
  591. <ul>
  592. <ul>
  593. <ul>
  594. <ul>
  595. <li>db &hellip; defines where to read. Note currently only writing in to DB are supported.</li>
  596. <li>DB &hellip; Number of the DB</li>
  597. <li>start &hellip; start byte of the reading</li>
  598. <li>{u8|s8|u16|s16|u32|s32} &hellip; defines the datatype:</li>
  599. <ul>
  600. <li>u8 &hellip;. unsigned 8 Bit integer</li>
  601. <li>s8 &hellip;. signed 8 Bit integer</li>
  602. <li>u16 &hellip;. unsigned 16 Bit integer</li>
  603. <li>s16 &hellip;. signed 16 Bit integer</li>
  604. <li>u32 &hellip;. unsigned 32 Bit integer</li>
  605. <li>s32 &hellip;. signed 32 Bit integer</li>
  606. <li>float &hellip;. 4 byte float</li>
  607. </ul>
  608. </ul>
  609. Note: the required memory area (start &ndash; start + datatypelength) need to be with in the configured PLC writing of the physical module.</ul>
  610. </ul>
  611. </ul>
  612. <p>Logo 7 / Logo 8</p>
  613. <p style="padding-left: 60px;">For Logo7 / Logo 8 also a short notation is supportet:</p>
  614. <p><code>define &lt;name&gt; S7_AWrite {AI|AM|AQ|NAI|NAQ}X</code></p>
  615. <p><strong>Set</strong><br /><br /><code>set &lt;name&gt; S7_AWrite &lt;value&gt;</code></p>
  616. <ul>
  617. <ul>
  618. <ul>
  619. <li>value &hellip; an numeric value</li>
  620. </ul>
  621. </ul>
  622. </ul>=end html_DE
  623. =cut