/** * handle incoming data along capabilities * @param array $data */ private function ParseData($data) { // $caps = $this->GetCaps(); //$this->debug(__FUNCTION__,print_r($this->all_caps,true)); foreach (array_keys($caps) as $cap) { $ident = $caps[$cap]; $vid = @$this->GetIDForIdent($ident); if ($vid == 0) { $this->debug(__FUNCTION__, "Cap {$cap} Ident {$ident}: Variable missed"); continue; } if (!isset($data[$cap])) { continue; } $s = $data[$cap]; switch ($cap) { //integer case 'TS': //Timestamp //Timestamp case 'Signal': //RSSI //RSSI case 'Timer': //Duration code //Duration code case 'Dimmer': //intensity 100% //intensity 100% case 'Shutter': //intensity 100% $iv = (int) $s; SetValueInteger($vid, $iv); break; //String //String case 'Name': //Duration code $st = utf8_decode($s); SetValueString($vid, $st); break; //special //special case 'Switch': //Status $state = $this->SwitchStatus($s); SetValueBoolean($vid, $state); break; case 'Lock': //Status $state = preg_match("/YES|CLOSE|OK/i", $s); //reversed SetValueBoolean($vid, $state); break; case 'Alert': //Status $state = !preg_match("/YES|ALERT/i", $s); //reversed SetValueBoolean($vid, $state); break; case 'Battery': //battery $state = !preg_match("/LOW|WARN/i", $s); //reversed SetValueBoolean($vid, $state); break; case 'FS20': //fs20 mode decoding $state = false; $intensity = 0; $timer = 0; $acode = ''; $actioncode = ''; $code = utf8_decode($s); $this->debug(__FUNCTION__, "FS20 Code " . strToHex($code)); $action = $code[0]; $ext = ord($code[1]); $tvid = @$this->GetIDForIdent($caps['Timer']); $dvid = @$this->GetIDForIdent($caps['Dimmer']); $swid = @$this->GetIDForIdent($caps['Switch']); $avid = @$this->GetIDForIdent($caps['TimerActionCode']); $this->debug(__FUNCTION__, "FS20 Vars S:{$swid},D:{$dvid},T:{$tvid},A:{$avid}"); if ($dvid) { $intensity = GetValueInteger($dvid); } if ($swid) { $state = GetValueBoolean($swid); } if ($tvid) { $timer = GetValueInteger($tvid); } if ($avid) { $acode = GetValueString($avid); } $ac = ord($action) & 0x1f; $timed = ($action & 0x20) > 0; $this->debug(__FUNCTION__, "FS20 AC:" . $ac . "PrevD:{$intensity}, PrevS:" . ($state ? "On" : "Off")); switch ($ac) { case 0: //off if ($timed) { $actioncode = 'Switch:Off'; } else { $state = false; } break; case $ac < 0xf: //Dim to value $intensity = FHZ_helper::fs20_intensity_percent($action & 0xf); $state = true; if ($timed) { $actioncode = 'Switch:Off'; } break; case 0x10: //on full $state = true; $intensity = 100; if ($timed) { $actioncode = 'Switch:Off'; } break; case 0x11: //on with old value $state = true; if ($intensity == 0) { $intensity = 100; } if ($timed) { $actioncode = 'Switch:Off'; } break; case 0x12: $state = !GetValueBoolean($swid); //toggle break; case 0x13: //dimup $steps = FHZ_helper::fs20_intensity_steps($intensity); $intensity = FHZ_helper::fs20_intensity_percent($steps + 1); $state = true; break; case 0x14: //dimdown if ($intensity == 0) { $intensity = 100; } $steps = FHZ_helper::fs20_intensity_steps($intensity); $intensity = FHZ_helper::fs20_intensity_percent($steps - 1); if ($intensity == 0) { $state = false; } break; case 0x18: //off-for-timer $state = 'Off'; $actioncode = 'Switch:On'; break; case 0x19: //on-for-timer than out $state = true; $actioncode = 'Switch:Off'; break; case 0x1a: //on-old-for-timer than out $state = true; $actioncode = 'Switch:Off'; break; case 0x1c: //ramp-on-time (time to reach the desired dim value on dimmers) $state = true; $actioncode = "Dimmer:{$intensity}"; break; case 0x1d: //ramp-off-time (time to reach the off state on dimmers) $actioncode = 'Switch:Off;Dimmer:0'; break; case 0x1e: //on-old-for-timer-prev", // old val for timer, then go to prev. state $actioncode = "Switch:" . ($state ? 'On' : 'Off'); $state = true; break; case 0x1f: //on-100-for-timer-prev", // 100% for timer, then go to previous state //new intensity will be the old one $action = "Switch:" . ($state ? 'On' : 'Off') . ";Dimmer:{$intensity}"; $intensity = 100; $state = true; break; case 0x15: //dimupdown, no value changes //dimupdown, no value changes case 0x16: //Set Timer //Set Timer case 0x17: //nop //nop case 0x1b: //rese break; } $new_timer = FHZ_helper::fs20_times($ext); $this->debug(__FUNCTION__, "State:" . ($state ? "ON" : "OFF") . ", Dimmer:{$intensity}%,Timer: {$new_timer},ActionCode: '{$actioncode}'"); //state if ($swid) { SetValueBoolean($swid, $state); } //dimmer if ($dvid) { SetValueInteger($dvid, $intensity); } //timer if ($tvid) { $this->SetTimerInterval('DeviceTimer', $new_timer * 1000); SetValueInteger($tvid, $new_timer); } //action if ($avid && $acode != $actioncode) { SetValueString($avid, $actioncode); } //log $actiontext = FHZ_helper::$fs20_codes[strToHex($action)]; if ($ext > 0) { $actiontext .= ', Timer:' . $timer; } $text = sprintf('%s (%s)', $actiontext, strToHex($code)); if ($vid) { SetValueString($vid, $text); } $this->debug(__FUNCTION__, "Action:" . $text); break; default: $this->debug(__FUNCTION__, "{$cap} not handled"); } $this->debug(__FUNCTION__, "{$cap}:({$vid})" . $s); } }
/** * prepare action request for sending to parent * @param array $data Interface Data */ private function SWD_ActionHandler($data) { $cap = $data['Cap']; $val = $this->SwitchStatus($data['Value']); $type = $data['Type']; $Device = $data['Device']; switch ($type) { case 'FS20': switch ($cap) { case 'Switch': $fs20code = $val ? "11" : "00"; break; case 'Dimmer': $steps = FHZ_helper::fs20_intensity_steps($val); $fs20code = sprintf("%02X", $steps); break; break; default: IPS_LogMessage(__CLASS__, __FUNCTION__ . 'invalid FS20 Action Command ' . $cap); return; } $culaddr = ''; if (strlen($Device) == 12) { $culaddr .= FHZ_helper::four2hex(substr($Device, 0, 8)); //hc $culaddr .= FHZ_helper::four2hex(substr($Device, 8, 4)); //sub $cul = 'F' . $culaddr . $fs20code; $this->debug(__FUNCTION__, "Send to FS20 Device {$Device} ({$culaddr}): {$cul}"); $this->SendText($cul . "\r\n"); } else { IPS_LogMessage(__CLASS__, __FUNCTION__ . "Invalid Device {$Device} Len<>12: " . strlen($Device)); } break; default: IPS_LogMessage(__CLASS__, __FUNCTION__ . "unsupported Type {$type}"); } }