Hallo Cervicor,
ja hab es geschafft Somfy RTS über einen CUL aus IPS zu steuern.
Ich versuche es so gut es geht zu beschreiben.
- CUL als seriellen Port anlegen (9600, Datenbits 8, Stopbit 1, keine Parität)
- Cutter instanz anlegen (hab aber gesehen dass ich keine Trennzeichen angegeben habe) kann man sich vermutlich sparen weil nur gesendet wird
- Register Variable anlegen und als Übergeordnete Instanz den Cutter angeben bzw. den seriellen Port direkt wenn kein Cutter erstellt wurde
- Unterhalb der Register Variablen ein Skript erstellen welches folgenden Inhalt hat (Ursprüngliche Quelle: http://www.tdressler.net/ipsymcon/cun_ips.html)
<?php
/**
* RegVar-Script für busware.de CUL/CUN receiver
* protocol decodes translated from FHEM project
* http://www.koeniglich.de/fhem/fhem.html
* testet with IPS 3.1 and CUN FW 1.46/COC FW 1.61 (ESA not tested)
* http://www.tdressler.net/ipsymcon
* V0.19 06.02.2015
* @package CUN
*/
//Regvar-Instance
$reg=55121 /*[CUL\Register Variable]*/;
#$reconnect=58270;
if (!IPS_InstanceExists($reg)) {
print "Instance with ID $reg doesnt exists";
return;
}
$inst=IPS_GetInstance($reg);
$ityp=$inst['ModuleInfo']['ModuleName'];
if ($ityp!="Register Variable") {
print "Instance $reg is not a 'Register Variable' Instance";
return;
}
//get message variable
$lmid=getVid('AuxMessage',$reg,3);
//load error variable
$errid=getVid('Errors',$reg,1);
$errors=GetValueInteger($errid);
setValue($errid,0);
//autocreate IPS Objects, set to false if you dont want this
$autocreate=true;
//logging
$logdir='../logs/';
$cullog=$logdir."cul.log";
//manual executed
if ($_IPS['SENDER'] == "Execute")
{
/*
Start/Stop Parent,
set Modus vis CUL_Status Event script capturing Status change
*/
//Status variablen
$versid=getVid('Version',$reg,3);
$mid=getVid('Modus',$reg,3);
//Parent=ClientSocket or ComPort
$sid=IPS_GetParent($reg);
if ($sid) {
$inst=IPS_GetInstance($sid);
$ityp=$inst['ModuleInfo']['ModuleName'];
if ($ityp=="Client Socket") {
setValue($mid,"");
setValue($versid,"");
//stop
CSCK_SetOpen($sid,false);
IPS_ApplyChanges($sid);
sleep(1);
//start
CSCK_SetOpen($sid,true);
IPS_ApplyChanges($sid);
}elseif($ityp=="Serial Port") {
setValue($mid,"");
setValue($versid,"");
//stop
ComPort_SetOpen($sid,false);
IPS_ApplyChanges($sid);
sleep(1);
//start
ComPort_SetOpen($sid,true);
IPS_ApplyChanges($sid);
}else{
print "Modultyp wrong";
return;
}
sleep(1);
$modus=getValue($mid);
print "Modus: $modus
";
$version=getValue($versid);
print "Version: $version
\r";
}else{
print "Parent not found";
}
}
//register variable triggerd action
elseif ($_IPS['SENDER'] == "RegisterVariable")
{
// bereits im Puffer der Instanz vorhandene Daten in $data kopieren
$data = RegVar_GetBuffer($reg);
// neu empfangene Daten an $data anhängen
$data .= $_IPS['VALUE'];
//split lines
$rows=preg_split("/
/",$data);
//reset Regvar Buffer
$data="";
RegVar_SetBuffer($reg, "");
foreach($rows as $line) {
//---------------EM1000-----------------------------------
if (preg_match("/^E[0-9A-F]{18,20}\s*\$/",$line)) {
// E0101E2997805002F02
$type=substr($line,2,1);
$addr=substr($line,3,2);
$addr_num=hexdec($addr);
$catname='EM1010CUL';
$sensorname='EM1010 Sensor';
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Last'=>array('type'=>1,'profile'=>'~UnixTimestamp'),
'Total'=>array('type'=>2,'profile'=>'~Electricity'),
'Actual'=>array('type'=>2,'profile'=>'~Power'),
'Peak'=>array('type'=>2,'profile'=>'~Power'),
'total_cnt'=>array('type'=>1,'profile'=>''),
'basis_cnt'=>array('type'=>1,'profile'=>''),
'cf_power'=>array('type'=>2,'profile'=>''),
'cf_energy'=>array('type'=>2,'profile'=>''));
$varids=get_ips_vars($addr,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
$cf1=$varids['cf_power']['val'];
$cf2=$varids['cf_energy']['val'];
$basis_cnt=$varids['basis_cnt']['val'];
$total_cnt_last=$varids['total_cnt']['val'];
$last=$varids['Last']['val'];
//ips_logmessage($catname,"1:$cf1,2:$cf2,B:$basis_cnt,T:$total_cnt_last,L:$last");
/*
Set corretion factor
corr1 is the correction factor for power
corr2 is the correction factor for energy
*/
$cfnew=(($cf1==0)||($cf2==0));
if($addr_num >= 1 && $addr_num <= 4) { // EMWZ: nRotation in 5 minutes
$cf1 = ($cf1 ? $cf1 : 150); //Zählerkonstanzte U/kwh
$cf2 = ($cf2 ? $cf2 : 150);
$corr1=12/$cf1;
$corr2=1/$cf2;
} elseif ($addr_num >= 5 && $addr_num <= 8) { // EMEM
$cf1 = ($cf1 ? $cf1 : 0.01);
$cf2 = ($cf2 ? $cf2 : 0.001);
$corr1=$cf1;
$corr2=$cf2;
} elseif($addr_num >= 9 && $addr_num <= 12) { // EMGZ: 0.01
$cf1 = ($cf1 ? $cf1 : 0.01);
$cf2 = ($cf2 ? $cf2 : 0.01);
$corr1=$cf1;
$corr2=$cf2;
} else {
IPS_Logmessage($catname,"Wrong Address:$addr");
setValue($errid,$errors+1);
continue 2;
return;
}
//store default factors
if ($cfnew) {
SetValue($varids['cf_power']['id'],$cf1);
SetValue($varids['cf_energy']['id'],$cf2);
}
/*
Decode Packet
description from CUL_EM.pm
Ettaacc111122223333
tt:type 01=EM-1000s, 02=EM-100-EM, 03=1000GZ
aa:address, depending on the type above 01:01-04, 02:05-08, 03:09-12
cc:counter, will be incremented by one for each message
1111: cumulated value
2222: last value (Not set for type 2)
3333: top value (Not set for type 2)
seqno = number of received datagram in sequence, runs from 2 to 255
total_cnt= total (cumulated) value in ticks as read from the device
basis_cnt= correction to total (cumulated) value in ticks to account for
counter wraparounds
total = total (cumulated) value in device units
current = current value (average over latest 5 minutes) in device units
peak = maximum value in device units
*/
$seqno=hexdec(substr($line,5,2));
//total value
$total_cnt=hexdec(substr($line,9,2).substr($line,7,2));
//counter overflow, max value 65535
if($total_cnt< $total_cnt_last) {
$basis_cnt += 65536;
SetValue($varids['basis_cnt']['id'],$basis_cnt);
}
$total = ($basis_cnt+$total_cnt)*$corr2;
SetValue($varids['total_cnt']['id'],$total_cnt);
//check time diff tp previous
$now=time();
$tdiff=$now-$last;
// peak and current (5min) value
if ($type<>2) {
$current_cnt=hexdec(substr($line,13,2).substr($line,11,2));
$peak_cnt=hexdec(substr($line,17,2).substr($line,15,2));
$current = $current_cnt*$corr1;
$peak = $peak_cnt*$corr1;
}else{
//calculate current as counter difference
if ($total_cnt>=$total_cnt_last) {
$current_cnt=$total_cnt-$total_cnt_last;
}else{
//add overflow
$current_cnt=$total_cnt+65536-$total_cnt_last;
}
//type 2 has no peak and current entry
$current = $current_cnt*$corr1;
$peak=0;
$peak_cnt=0;
}
//store in IPS
SetValue($varids['Total']['id'],$total);
SetValue($varids['Actual']['id'],$current);
SetValue($varids['Peak']['id'],$peak);
SetValue($varids['Last']['id'],$now);
//signal
if ( strlen($line)>19) {
SetSignal($varids['Signal']['id'],substr($line,19,2));
}
//logging to IPS log
$val = sprintf("SEQ: %d CNT: %d Basis: %d DIFF: %d TIME:$tdiff CUM: %0.3f 5MIN: %0.3f PEAK: %d TOP: %0.3f",
$seqno, $total_cnt, $basis_cnt,$current_cnt,$total, $current,$peak_cnt, $peak);
$text= "Type $type Addr:$addr, $val";
//logging
IPS_Logmessage($catname,$text);
}//if pregmatch
//-----------------------FS20
elseif (preg_match("/^F[0-9A-F]{8,12}\s*\$/",$line)) {
//F1F1E013A4F
$hcode=substr($line,1,4);
$addr=substr($line,5,2);
$cde=substr($line,7,2);
$id=hex2four($hcode.$addr);
if (strlen($id)==12)$id=substr($id,0,4).' '.substr($id,4,4).' '.substr($id,8,4);
$catname='FS20CUL';
$sensorname='FS20 ';
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Status'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>'')
);
$varids=get_ips_vars($id,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
$fs20_codes = array(
//definitions taken from http://www.elv.de/downloads/faq/Zuordnung_interne_Programmbezeichnungen_zu_FS20_Befehlcodes.pdf
"00" => "off",
"01" => "dim06%",
"02" => "dim12%",
"03" => "dim18%",
"04" => "dim25%",
"05" => "dim31%",
"06" => "dim37%",
"07" => "dim43%",
"08" => "dim50%",
"09" => "dim56%",
"0A" => "dim62%",
"0B" => "dim68%",
"0C" => "dim75%",
"0D" => "dim81%",
"0E" => "dim87%",
"0F" => "dim93%",
"10" => "dim100%/On",
"11" => "Dim to previous", // Set to previous dim value (before switching it off)
"12" => "toggle", // between off and previous dim val
"13" => "dimup",
"14" => "dimdown",
"15" => "dimupdown",
"16" => "set timer",
"17" => "nop",
"18" => "off-for-timer",
"19" => "on-for-timer than out",
"1A" => "on-old-for-timer than out",
"1B" => "reset",
"1C" => "ramp-on-time", //time to reach the desired dim value on dimmers
"1D" => "ramp-off-time", //time to reach the off state on dimmers
"1E" => "on-old-for-timer-prev", // old val for timer, then go to prev. state
"1F" => "on-100-for-timer-prev", // 100% for timer, then go to previous state
"20" => "Timer off",
"21" => "Dim Timer to 06%",
"22" => "Dim Timer to 12%",
"23" => "Dim Timer to 18%",
"24" => "Dim Timer to 25%",
"25" => "Dim Timer to 31%",
"26" => "Dim Timer to 37%",
"27" => "Dim Timer to 43%",
"28" => "Dim Timer to 50%",
"29" => "Dim Timer to 56%",
"2A" => "Dim Timer to 62%",
"2B" => "Dim Timer to 68%",
"2C" => "Dim Timer to 75%",
"2D" => "Dim Timer to 81%",
"2E" => "Dim Timer to 87%",
"2F" => "Dim Timer to 93%",
"30" => "Dim Timer to 100%/On",
"31" => "Dim Timer to previous", // Set to previous dim value (before switching it off)
"32" => "toggle", // between off and previous dim val
"33" => "Dim Timer up one level",
"34" => "Dim Timer down one level",
"35" => "updown one level, out after Timer ",
"36" => "set timer",
"37" => "nop",
"38" => "off-for-timer",
"39" => "on-for-timer than out",
"3A" => "on-to-old-for-timer than out",
"3B" => "reset",
"3C" => "ramp-on-time", //time to reach the desired dim value on dimmers
"3D" => "ramp-off-time", //time to reach the off state on dimmers
"3E" => "on-old-for-timer-prev", // old val for timer, then go to prev. state
"3F" => "on-100-for-timer-prev", // 100% for timer, then go to previous state
);
if (isset($fs20_codes[$cde])) {
$v =$fs20_codes[$cde];
}else {
$v = "unknown Code $cde" ;
setValue($errid,$errors+1);
IPS_Logmessage($catname,"Err:$errors ($v)");
continue ;
}
$varids=get_ips_vars($id,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
$dur = 0;
$cx = hexdec($cde);
if($cx & 0x20) {
$dur = hexdec(substr($line, 9, 2));
$i = ($dur & 0xf0) / 16;
$j = ($dur & 0xf);
$dur = pow(2,$i)*$j*0.25;
$cde = sprintf("%02x", $cx & ~0x20);
}
if($dur) $v .= " DUR: $dur" ;
//signal
if ( strlen($line)>11) {
SetSignal($varids['Signal']['id'],substr($line,11,2));
}else{
//signal
if ( strlen($line)>9) {
SetSignal($varids['Signal']['id'],substr($line,9,2));
}
}
$text= "Dev $id: $v($cde)";
SetValue($varids['Status']['id'],$v);
//logging
IPS_Logmessage($catname,$text);
} //if pregmatch
//------------------FHT----------------------------------
elseif (preg_match("/^(T[0-9A-F]{8,12})\s*\$/",$line,$res)) {
//T4414B90106
//T0A4700BA00
//T500CFD8237
$varids=null;
$res=$res[1];
$dev = substr($res, 1, 4);
$cde = substr($res, 5, 2);
if(strlen($res) <12 ) {
//TFK with signal
$dev = substr($res, 1, 6);
$cde = substr($res, 7, 2);
$val=$res;
$catname='FHTTFKCUL';
$sensorname='FHTTFK ';
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Window'=>array('type'=>3,'profile'=>''),
'Warnings'=>array('type'=>3,'profile'=>''),
'Status'=>array('type'=>3,'profile'=>''));
$varids=get_ips_vars($dev,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
$FHT_tfk_codes = array(
"02" => "Window:Closed",
"82" => "Window:Closed",
"01" => "Window:Open",
"81" => "Window:Open",
"0C" => "Sync:Syncing",
"91" => "Window:Open, Low Batt",
"11" => "Window:Open, Low Batt",
"92" => "Window:Closed, Low Batt",
"12" => "Window:Closed, Low Batt",
"0F" => "Test:Success");
switch ($cde) {
case "01":
case "81": $win="open";
SetValue($varids['Window']['id'],$win);
break;
case "02":
case "82": $win="closed";
SetValue($varids['Window']['id'],$win);
break;
case "11":
case "91": $win="open";
$warn="Low Batt";
SetValue($varids['Window']['id'],$win);
SetValue($varids['Warnings']['id'],$warn);
break;
case "12":
case "92": $win="closed";
$warn="Low Batt";
SetValue($varids['Window']['id'],$win);
SetValue($varids['Warnings']['id'],$warn);
break;
default: break;
}
//signal
if ( strlen($res)>9) {
SetSignal($varids['Signal']['id'],substr($res,9,2));
}
$val="";
$cmd=isset($FHT_tfk_codes[$cde])?$FHT_tfk_codes[$cde]:"Unknown TFK:$cde";
SetValue($varids['Status']['id'],"$cmd");
$text="FHT TFK Dev $dev:";
$text.= " $cmd" ;
//logging
IPS_Logmessage($catname,$text);
} else {
$catname='FHTCUL';
$sensorname='FHT ';
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'HC'=>Array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Low'=>array('type'=>3,'profile'=>''),
'Position'=>array('type'=>3,'profile'=>''),
'Warnings'=>array('type'=>3,'profile'=>''),
'Soll'=>array('type'=>2,'profile'=>'~Temperature'),
'Temperatur'=>array('type'=>2,'profile'=>'~Temperature'),
'Status'=>array('type'=>3,'profile'=>''));
$varids=get_ips_vars($dev,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
$FHT_codes = array(
"00" => "actuator",
"01" => "actuator1",
"02" => "actuator2",
"03" => "actuator3",
"04" => "actuator4",
"05" => "actuator5",
"06" => "actuator6",
"07" => "actuator7",
"08" => "actuator8",
"14" => "mon-from1",
"15" => "mon-to1",
"16" => "mon-from2",
"17" => "mon-to2",
"18" => "tue-from1",
"19" => "tue-to1",
"1A" => "tue-from2",
"1B" => "tue-to2",
"1C" => "wed-from1",
"1D" => "wed-to1",
"1E" => "wed-from2",
"1F" => "wed-to2",
"20" => "thu-from1",
"21" => "thu-to1",
"22" => "thu-from2",
"23" => "thu-to2",
"24" => "fri-from1",
"25" => "fri-to1",
"26" => "fri-from2",
"27" => "fri-to2",
"28" => "sat-from1",
"29" => "sat-to1",
"2A" => "sat-from2",
"2B" => "sat-to2",
"2C" => "sun-from1",
"2D" => "sun-to1",
"2E" => "sun-from2",
"2F" => "sun-to2",
"3E" => "mode",
"3F" => "holiday1", # Not verified
"40" => "holiday2", # Not verified
"41" => "desired-temp",
"XX" => "measured-temp", # sum of next. two, never really sent
"42" => "measured-low",
"43" => "measured-high",
"44" => "warnings",
"45" => "manu-temp", # No clue what it does.
"4B" => "ack",
"53" => "can-xmit",
"54" => "can-rcv",
"60" => "year",
"61" => "month",
"62" => "day",
"63" => "hour",
"64" => "minute",
"65" => "report1",
"66" => "report2",
"69" => "ack2",
"7D" => "start-xmit",
"7E" => "end-xmit",
"82" => "day-temp",
"84" => "night-temp",
"85" => "lowtemp-offset", # Alarm-Temp.-Differenz
"8A" => "windowopen-temp"
);
// additional warnings
$FHT_warnings = array(
"battery" => 1,
"lowtemp" => 1,
"window" => 1,
"windowsensor" => 1,
);
$FHT_priority = array(
"desired-temp"=> 1,
"mode" => 2,
"report1" => 3,
"report2" => 3,
"holiday1" => 4,
"holiday2" => 5,
"day-temp" => 6,
"night-temp" => 7,
);
$FHT_c2m = array(0 => "auto", 1 => "manual", 2 => "holiday", 3 => "holiday_short");
$hc=hexdec($dev);
$house=sprintf("%02d %02d",($hc >>8), ($hc & 255));
SetValue($varids['HC']['id'],"$house");
$text="Dev: $dev (HC $house)";
if(strlen($line) > 9) $val = substr($line, 9, 2);
//signal
if ( strlen($line)>11) {
SetSignal($varids['Signal']['id'],substr($line,11,2));
}
if(!$val || $cde == "65" || $cde == "66") {
// This is a confirmation message. We reformat it so that
$confirm = 1;
}
$val = hexdec($val);
$cmd = isset($FHT_codes[$cde])?$FHT_codes[$cde]:"";
if(!$cmd) {
$cmd= "(Unknown: $cde =>$val)";
$val="";
//continue;
setValue($errid,$errors+1);
goto fhtlog;
}
if( preg_match("/-from/",$cmd) || preg_match("/-to/",$cmd)) {
$val = sprintf("%02d:%02d", $val/6, ($val%6)*10);
} elseif($cmd == "mode") {
if(isset($c2m[$val])) $val = $c2m[$val] ;
} elseif(preg_match("/.*-temp/",$cmd)) {
$val=$val/2;
if ($cmd== "desired-temp") {
SetValue($varids['Soll']['id'],$val);
}
$val = sprintf("%.1f", $val);
} elseif($cmd == "lowtemp-offset") {
$val = sprintf("%d.0", $val);
} elseif(preg_match("/^actuator/",$cmd)) {
$id=substr($line,6,1);
$sval = substr($line,7,2);
$fv = sprintf("%d%%", (integer)(100*$val/255+0.5));
if(preg_match("/[AB]0/i",$sval)) { $val = $fv; } # sync in the summer
elseif(preg_match("/.0/",$sval)) { $val = "syncnow"; }
elseif(preg_match("/.1/",$sval)) { $val = "99%"; } # FHT set to 30.5, FHT80B=="ON"
elseif(preg_match("/.2/",$sval)) { $val = "0%"; } # FHT set to 5.5
elseif(preg_match("/.6/",$sval)) { $val = "$fv"; }
elseif(preg_match("/.8/",$sval)) { $val = "offset: $fv"; }
elseif(preg_match("/.A/",$sval)) { $val = "lime-protection"; }
elseif(preg_match("/.C/",$sval)) { $val = sprintf("synctime: %d", int($val/2)-1); }
elseif(preg_match("/.E/",$sval)) { $val = "test"; }
elseif(preg_match("/.F/",$sval)) { $val = "pair"; }
else { $val = "unknown_$sval: $fv"; }
$pos=strpos($val,"%");
if (! ($pos===false)) {
if ($id=="0") {
SetValue($varids['Position']['id'],$val);
}else{
$pid==getVid('Position'.$id,IPS_GetParent($varids['ID']['id']));
if (! $pid==false) {
SetValue($pid,$val);
}
}
}
} elseif($cmd == "measured-low") {
SetValue($varids['Low']['id'],$val);
//continue;
goto fhtlog;
} elseif($cmd == "measured-high") {
// if(defined($varids['Low']['val'])) {
$low=$varids['Low']['val'];
$off = 0;
$val = $val*256 + $low;
$val /= 10;
SetValue($varids['Temperatur']['id'],$val);
$val = sprintf("%.1f (Celsius)", $val+$off);
$cmd = "measured-temp";
} elseif($cmd == "warnings") {
# initialize values for additional warnings
# parse warnings
if($val & 1) {
$nVal = "Battery low";
$nBattery = "low";
}
if($val & 2) {
if($nVal) $nVal .= "; " ;
$nVal .= "Temperature too low";
$nLowTemp = "warn";
}
if($val &32) {
if($nVal) $nVal .= "; " ;
$nVal .= "Window open";
$nWindow = "open";
}
if($val &16) {
if($nVal) $nVal .= "; " ;
$nVal .= "Fault on window sensor";
$nSensor = "fault";
}
# set default values or new values if they were changed
$valBattery = isset($nBattery)? $nBattery : "ok";
$valLowTemp = isset($nLowTemp)? $nLowTemp : "ok";
$valWindow = isset($nWindow)? $nWindow : "closed";
$valSensor = isset($nSensor)? $nSensor : "ok";
$val = isset($nVal)? $nVal : "none";
# set additional warnings and trigger notify
$text.= " battery: $valBattery";
$text.= " lowtemp: $valLowTemp";
$text.= " window: $valWindow";
$text.= " windowsensor: $valSensor";
SetValue($varids['Warnings']['id'],"$val");
}
//finish
fhtlog:
if(substr($line,7,1) == "7") { # Do not store FHZ acks.
$cmd = "FHT:$cmd";
$text.="
".$cmd;
} else {
//if($cmd == "measured-temp")
$text.= " $cmd: $val" ;
SetValue($varids['Status']['id'],"$cmd: $val");
}
//logging
IPS_Logmessage($catname,$text);
}//if strlen
}//if preg
//---------------------Wetter(WS300)-----------------------------------------
elseif (preg_match("/^K[0-9A-F]{6,16}\s*\$/",$line)) {
//K11245265,K41815177F4
$tlist = array("0"=>"temp",
"1"=>"temp/hum",
"2"=>"rain",
"3"=>"wind",
"4"=>"temp/hum/press",
"5"=>"brightness",
"6"=>"pyro",
"7"=>"temp/hum");
$a=str_split($line);
$len=strlen($line)-1; //last is cr
$firstbyte = hexdec($a[1]);
$typebyte=$a[2];
$cde = (string)($firstbyte&7);
$type = isset($tlist[$typebyte]) ? $tlist[$typebyte] : "unknown";
$typebyte=$typebyte & 7;
$varids=null;
$val="no data";
$catname='WSCUL';
$sensorname='WS ';
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Temperatur'=>array('type'=>2,'profile'=>'~Temperature'),
'Humidity'=>array('type'=>1,'profile'=>'~Humidity')
);
$varids=get_ips_vars($cde,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
if (($firstbyte&7)==7) {
if($typebyte == 0 && $len > 6) { # temp
$sgn = ($firstbyte&8) ? -1 : 1;
$tmp = $sgn * ($a[6].$a[3].".".$a[4]);
$val = "T: $tmp";
$hum=0;
SetValue($varids['Temperatur']['id'],$tmp);
SetValue($varids['Humidity']['id'],$hum);
}
if($typebyte == 1 && $len > 8) { # temp/hum
$sgn = ($firstbyte&8) ? -1 : 1;
$tmp = $sgn * ($a[6].$a[3].".".$a[4]);
//$hum = ($a[7].$a[8].".".$a[5]) ;
$hum = ($a[7].$a[8]) ;
$val = "T: $tmp H: $hum";
$devtype = "PS50";
$family = "WS300";
SetValue($varids['Temperatur']['id'],$tmp);
SetValue($varids['Humidity']['id'],$hum);
}
//signal
if ( $len>9) {
SetSignal($varids['Signal']['id'],substr($line,19,2));
}
}else{
if ($len < 12 ) { # S300TH
$sgn = ($firstbyte&8) ? -1 : 1;
$tmp = $sgn * ($a[6].$a[3].".".$a[4]);
//$hum = ($a[7].$a[8].".".$a[5]);
$hum = ($a[7].$a[8]) ;
$val = "T: $tmp H: $hum";
$devtype = "S300TH";
SetValue($varids['Temperatur']['id'],$tmp);
SetValue($varids['Humidity']['id'],$hum);
//signal
if ( $len==10) {
SetSignal($varids['Signal']['id'],substr($line,9,2));
}
} elseif($len > 13) { # KS300/2
$c = 255;
$rain = sprintf("%0.1f", hexdec($a[14].$a[11].$a[12]) * $c / 1000);
$wnd = sprintf("%0.1f", $a[9].$a[10].$a[7] );
$hum = sprintf( "%02d", $a[8].$a[5]);
$tmp = sprintf("%0.1f", ($a[6].$a[3].$a[4]),
(($a[1] & 0xC) ? -1 : 1));
$ir = ((hexdec($a[1]) & 2)) ? "yes" : "no";
SetValue($varids['Temperatur']['id'],$tmp);
SetValue($varids['Humidity']['id'],$hum);
$val = "T: $tmp H: $hum W: $wnd R: $rain IR: $ir";
}
//signal
if ( $len==15) {
SetSignal($varids['Signal']['id'],substr($line,15,2));
}
}
$text="Dev $cde ($type): $val";
IPS_Logmessage($catname,$text);
}//if preg
//--------------------HMS-------------------------------------------------------
elseif (preg_match("/^H[0-9A-F]{12,14}\s*\$/",$line)) {
//H37AE01240000
$codes = array(
0 => "HMS100TF",
1 => "HMS100T",
2 => "HMS100WD",
3 => "RM100-2",
4 => "HMS100TFK", # Depending on the onboard jumper it is 4 or 5
5 => "HMS100TFK",
6 => "HMS100MG",
8 => "HMS100CO",
14 => "HMS100FIT"
);
$type = hexdec(substr($line,6,1));
$stat = $type > 1 ? hexdec(substr($line,7,2)) : hexdec(substr($line,5,2));
$prf = $type > 1 ? "02" : "05";
$bat = $type > 1 ? hexdec(substr($line,5,1))+1 : 1;
$dev = substr($line,1,4);
$val = $type > 1 ? "000000" : substr($line,7);
$catname='HMSCUL';
$sensorname='HMS ';
//if (!isset($sensorname)) $sensorname='HMS ';
switch ($type) {
case 0://TF
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Type'=>array('type'=>3,'profile'=>''),
'Temperatur'=>array('type'=>2,'profile'=>'~Temperature'),
'Humidity'=>array('type'=>1,'profile'=>'~Humidity'),
'Battery'=>array('type'=>0,'profile'=>'~Battery.Reversed')
);
break;
case 1://T
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Type'=>array('type'=>3,'profile'=>''),
'Temperatur'=>array('type'=>2,'profile'=>'~Temperature'),
'Battery'=>array('type'=>0,'profile'=>'~Battery.Reversed')
);
break;
case 4://TFK Switch1
case 5://TFK Switch2
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Type'=>array('type'=>3,'profile'=>''),
'Kontakt'=>array('type'=>0,'profile'=>'~Switch'),
'Battery'=>array('type'=>0,'profile'=>'~Battery.Reversed')
);
break;
case 2://WD
case 3://RM100
case 6://Gas MG
case 8://Gas CO
case 14://FIT
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'Type'=>array('type'=>3,'profile'=>''),
'Alarm'=>array('type'=>0,'profile'=>'~Alert'),
'Battery'=>array('type'=>0,'profile'=>'~Battery.Reversed')
);
break;
default://type not known
IPS_LogMessage($catname,"Unknown type: $type");
setValue($errid,$errors+1);
continue 2;
}
$varids=null;
$varids=get_ips_vars($dev,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
SetValue($varids['Battery']['id'],($bat==1));
if (! ($varids['Type']['val']) == $codes[$type]) {
SetValue($varids['Type']['id'],$codes[$type]);
}
switch($type) {
case 0: //TF
# Codierung <t1><t0><f0><t2><f2><f1>
$hum=(Integer)(substr($val, 4, 2).substr($val, 2, 1))/10;
SetValue($varids['Humidity']['id'],$hum);
case 1://T
$tmp=(substr($val, 3, 1).substr($val, 0, 2))/10;
if (($stat & 128)>0) $tmp=-$tmp;
SetValue($varids['Temperatur']['id'],$tmp);
break;
case 2:
case 3:
case 6:
case 8:
case 14: SetValue($varids['Alarm']['id'],($stat>0));
break;
case 4:
case 5: SetValue($varids['Kontakt']['id'],($stat>0));
break;
default:
IPS_LogMessage($catname,"Type $type for Dev $HA not known");
break;
}
//signal
if ( strlen($line)>13) {
SetSignal($varids['Signal']['id'],substr($line,13,2));
}
$text="Dev $dev ($type:".$codes[$type]."): Stat:$stat, Bat: $bat Val: $val";
IPS_Logmessage($catname,$text);
}//if preg
//--------------------ESA-------------------------------------------------------
elseif (preg_match("/^S[0-9A-F]{32,34}\s*\$/",$line)) {
# definitions taken from FHEM 64_ESA2000.pm
# S6E003D011E00037650001102C1DA07D01D
# S 6E 003D 011E 00037650 0011 02C1DA 07D0 1D
# 1 2 3
# 0 12 3456 7890 12345678 9012 345678 9012 34
# seqno = number of received datagram in sequence mod 128(repeated if seqno/128 >0)
# code = device code
# type = type of sensor: 011E: ESA1000-WZ, ...
# total_cnt = total (cumulated) value in ticks as read from the device
# current_cnt = current value (average over latest 5 minutes) in device units
# timestamp = current time from start of device in 10 sec units
# ticks = ticks per kWh setup in ESA1000WS (depends on the meter)
$codelist = array(
"003D" => "ESA1000-S0",
"0055" => "ESA1000-S0",
"44C7" => "ESA2000_LED",
"0178" => "ESA2000_LED",
"0595" => "ESA1000GAS",
"01FA" => "ESA2000_LED"
);
$tlist=array("011E"=>"ESA1000-WZ");
$seqno= hexdec(substr($line,1,2))%128;
$code = substr($line,3,4);
$type = substr($line,7,4);
$dev=$code."-".$type;
$total_cnt=hexdec(substr($line,11,8));
$current_cnt=hexdec(substr($line,19,4));
$timestamp=hexdec(substr($line,23,6));
$ticks=hexdec(substr($line,29,4));
$catname='ESACUL';
$sensorname = isset($codelist[$code]) ? $codelist[$code] : "ESA ";
$varids=null;
$vartypes=array( 'ID'=>array('type'=>3,'profile'=>''),
'Signal'=>array('type'=>1,'profile'=>''),
'total'=>array('type'=>1,'profile'=>''),
'current'=>array('type'=>1,'profile'=>''),
'ticks'=>array('type'=>1,'profile'=>'')
);
$varids=get_ips_vars($dev,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
//no vars available, maybe autocreate disabled
continue;
}
SetValue($varids['total']['id'],$total_cnt);
SetValue($varids['current']['id'],$current_cnt);
SetValue($varids['ticks']['id'],$ticks);
//signal
if ( strlen($line)>32) {
SetSignal($varids['Signal']['id'],substr($line,33,2));
}
$text="Dev $dev : Tot:$total_cnt, Cur: $current_cnt Ticks: $ticks";
IPS_Logmessage($catname,$text);
}//if preg
#-----------aux/unknown/unimplemented cul/cun/coc message------
elseif (! preg_match("/^\s*$/",$line)) {
IPS_Logmessage('CUL','MSG:'.$line);
setValue($lmid,$line);
//--------------------OneWire---------------------------------------------
if (preg_match("/^R:[0-9A-F]{16}\s*\$/",$line)) {
IPS_Logmessage('CUL','OneWire Device:'.substr($line,2));
}
elseif (preg_match("/^D:\s*([0-9]+)\s*\$/",$line,$res)) {
IPS_Logmessage('CUL','OneWire detected Devices:'.$res[1]);
}
elseif (preg_match("/^\s*(ON|OFF)\s*\$/",$line,$res)) {
IPS_Logmessage('CUL','OneWire HMS Emulation:'.$res[1]);
}
elseif (preg_match("/^Y\w[0-9A-F]{1,16}\s*\$/",$line,$res)) {
IPS_Logmessage('CUL','Somfy Emulation');
}
//------ Init messages --------------
elseif(preg_match("/^(V\s*[0-9\.]+)\s*CSM.*/",$line,$res)) {
IPS_Logmessage('CUL','Version:'.$res[1]);
}
elseif(preg_match("/^[0-9]{2}\s+[0-9]{3}/",$line,$res)) {
IPS_Logmessage('CUL','Modus:'.substr($line,2));
//--------- Error -------------
}else {
$errors=$errors+1;
IPS_Logmessage('CUL','Err:'.$errors.' MSG:'.$line);
setValue($errid,$errors);
if ($errors>10) {
//to many errors, reset COC
if ($reconnect && IPS_ScriptExists($reconnect)) {
IPS_RunScript($reconnect);
}
}//errors
}//preg others
}//preg
}//foreach
}//if sender
//-------------------------------------------------------------------------------
/**
* IPS Variablen handler
* creates variables as needed
* returns assoc. Array with IPS Variable ID and Value
* @param integer Sensor Address
* @param array Array with Variable Names, Types and Profiles
* @param string Sensor Group Master Categorie Name
* @param string Sensor default name, will be extended with $addr
*/
function get_ips_vars($addr,$vartypes,$cat,$sens) {
$varids=null;
$master=@IPS_GetObjectIDByName($cat,0);
//no master cat, create new
if (!$master) {
$master=IPS_CreateCategory();
IPS_SetName($master,$cat);
IPS_SetParent($master,0);
if ($master>0) {
IPS_LogMessage('CUL', "Master category created, ID=$master
");
}else{
IPS_LogMessage('CUL', "Can't create Master Category
");
return null;
}
}
$id=0;
if ($master>0) {
//get chilren sensors
$Sensors=IPS_GetChildrenIDs($master);
foreach($Sensors as $sid) {
$name=IPS_GetName($sid);
//print "$sid:".$name."
";
//get vars for each sensor
$vars=IPS_GetChildrenIDs($sid);
foreach($vars as $vid) {
$obj=IPS_GetObject($vid);
$vname=$obj['ObjectName'];
$typ=$obj['ObjectType'];
if ($typ==2) { //Variable
//if ID, here is the address
if ($vname="ID") {
$i=GetValue($vid);
//go out if matches, $id returns the sensor categorie id
if ($i===$addr) {
$id=$sid;
break;
}
}
}
}
if ($id>0) break;
}
if ($id==0) {
//Sensor with address $addr not found in IPS
if ($GLOBALS['autocreate']==false) {
//autocreate disable, ignore new device
return null;
}
//create new sensor
$id=ips_createCategory();
ips_setName($id,$sens.' '.$addr);
ips_setParent($id,$master);
//creates all needed variables for the new sensor
foreach (array_keys($vartypes) as $name) {
$typ=$vartypes[$name]['type'];
$profile=$vartypes[$name]['profile'];
$vid=IPS_CreateVariable($typ);
ips_setname($vid,$name);
ips_setParent($vid,$id);
IPS_SetVariableCustomProfile($vid,$profile);
//preload variables
SetValue($vid,0);
$varids[$name]['id']=$vid;
$varids[$name]['val']=0;
//Store address in $ID for next time
if ($name=='ID') {
SetValue($vid,$addr);
$varids[$name]['val']=$addr;
}
}
}else{
//found matching cat, collect ids and vals for this sensor
$vars=IPS_GetChildrenIDs($id);
foreach($vars as $vid) {
$obj=IPS_GetObject($vid);
$name=$obj['ObjectName'];
$typ=$obj['ObjectType'];
if ($typ==2) { //Variable
$val=GetValue($vid);
$varids[$name]['id']=$vid;
$varids[$name]['val']=$val;
}
}
}
//returns IDs and Values of this Sensor, Name is Key
return $varids;
}
}
//#############################
//
/**
* converting CUL Hex IDs into ELV-4-Ids
* translated from 10_fs20
* @param string $v Hex-Value
* @returns string ELV-ID
*/
function hex2four($v){
$r = "";
foreach (str_split($v) as $x) {
$r .= sprintf("%d%d", (hexdec($x)/4)+1, (hexdec($x)%4)+1);
}
return $r;
}
//#############################
/**
* do simple logging
* @param string $logfile Filename for logfile
* @param string $text
* @returns void
*/
function logge($logfile,$text) {
if (strlen($logfile)>0) {
$log=fopen($logfile,"a+");
if ($log) {
$d=date("r");
fwrite($log,"$d $text");
fflush($log);
fclose($log);
}
}
}
/**
* Get ID by name if exists, else create
* @Param String Name
* @param integer Parent-ID
* @param integer Variable Typ (0..3)
* @return integer ID
*/
function getVid($name,$par,$typ) {
$vid = @IPS_GetVariableIDByName($name, $par);
if ($vid === false) {
$vid=IPS_CreateVariable($typ);
ips_setname($vid,$name);
ips_setParent($vid,$par);
setValue($vid,'');
}
return $vid;
}
/**
* set signal strange (in dB)
* @Param Integer ID Signal Variable
* @param String Hex-Byte
*/
function setSignal($sid,$hex) {
$rssi=hexdec($hex);
if ($rssi>=128) {
$rssi=(($rssi-256)/2)-74;
} else {
$rssi=($rssi/2)-74;
}
$rssi=intval($rssi);
//IPS_Logmessage('CUL',"Signal: $rssi ($hex) Id $sid");
setValue($sid,$rssi);
}
?>