- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
/D_RFXCOM.json
r1 r3 106 106 } 107 107 }, 108 {108 { 109 109 "ControlType": "label", 110 110 "Label": { … … 151 151 ] 152 152 } 153 } 153 } 154 154 ] 155 155 }, -
/I_RFXCOM.xml
r1 r3 5 5 </settings> 6 6 <functions> 7 7 8 local RFX_SERVICE = "urn:upnp-esweb-nl:serviceId:rfxcom1" 8 9 socket = require("socket") 9 bitw = require("bit") 10 startupReady = 0 11 startTime = 0 12 endTime = 0 13 buffer = "" 14 RFXmsgTable = {} 15 RFXLastMsg = "" 16 ipAddress = "" 17 ipPortRead = 0 18 ipPortSend = 0 19 RFXCOM_HAR_Count = 0 20 RFXCOM_HAR_Devices = {} 21 10 bitw = require("bit") 11 startupReady = 0 12 startTime = 0 13 endTime = 0 14 buffer = "" 15 RFXmsgTable = {} 16 RFXLastMsg = "" 17 ipAddress = "" 18 ipPortRead = 0 19 ipPortSend = 0 20 21 RFXConstants = { 22 sensorTypeMotion = "MOTION", 23 sensorTypeDoor = "DOOR", 24 sensorTypeKeyFob = "KEYFOB", 25 sensorTypeWeather = "WEATHER", 26 sensorTypeRemote = "REMOTE", 27 sensorTypeControler = "CONTROLER", 28 sensorTypeWindowCovering = "WINDOWCOVERING", 29 30 sensorManufacturerX10 = "X10", 31 sensorManufacturerHomeEasy = "HOMEEASY", 32 sensorManufacturerVisonic = "VISONIC", 33 sensorManufacturerOregon = "OREGON", 34 sensorManufacturerHarrison = "HARRISON", 35 36 cmdGroupOn = 1, 37 cmdGroupOff = 2, 38 cmdOn = 4, 39 cmdOff = 8, 40 cmdArmAway = 16, 41 cmdArmHome = 32, 42 cmdDisarm = 64, 43 cmdTamper = 128, 44 cmdJamming = 256, 45 cmdBatteryLow = 512, 46 cmdNormal = 1024, 47 cmdAlert = 2048 48 } 49 22 50 function mainStartup(lul_device) 23 THIS_DEVICE = lul_device 24 25 luup.log("Starting RFXCOM device: " .. tostring(THIS_DEVICE)) 26 27 local device = luup.devices[THIS_DEVICE] 28 29 if (device.ip == "") then 30 return false, "IP Address attribute must be configured", "rfxcom" 31 end 32 33 ipAddress = device.ip 34 35 for k, v in pairs(luup.devices) do 36 if (v.device_num_parent == lul_device) then 37 luup.log( "Found child device, lets save! id " .. tostring(v.id) .. " device " .. tostring(v.device_type)) 38 39 if (tostring(v.device_type) == "urn:schemas-micasaverde-com:device:WindowCovering:1") then 40 RFXCOM_HAR_Count = RFXCOM_HAR_Count + 1 41 RFXCOM_HAR_Devices[RFXCOM_HAR_Count] = v.id 42 end 43 end 44 end 45 46 47 local portList = luup.variable_get("urn:upnp-esweb-nl:serviceId:rfxcom1", "portRead", lul_device) 48 if ((portList or "") == "") then 49 portList = "10001" 50 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "portRead", portList, lul_device) 51 elseif (portList:find("%d") == nil) then 52 return false, "The Port Read parameter must be of the form nnnn. eg. 10001" 53 end 54 55 ipPortRead = portList 56 57 local portList = luup.variable_get("urn:upnp-esweb-nl:serviceId:rfxcom1", "portWrite", lul_device) 58 if ((portList or "") == "") then 59 portList = "10002" 60 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "portWrite", portList, lul_device) 61 elseif (portList:find("%d") == nil) then 62 return false, "The Port Write parameter must be of the form nnnn. eg. 10002" 63 end 64 65 ipPortSend = portList 66 67 luup.log("Open socket for read " .. ipAddress .. " port " .. ipPortRead ) 68 69 luup.io.open(THIS_DEVICE, ipAddress, ipPortRead) 70 71 startupReady = 1 72 73 return true, "ok", "rfxcom" 51 RFXDevicesLS = {} 52 RFXCountLS = 0 53 RFXDevicesDS = {} 54 RFXCountDS = 0 55 RFXDevicesMS = {} 56 RFXCountMS = 0 57 RFXDevicesKF = {} 58 RFXCountKF = 0 59 RFXCOM_HAR_Count = 0 60 RFXCOM_HAR_Devices = {} 61 62 THIS_DEVICE = lul_device 63 luup.log("Starting RFXCOM device: " .. tostring(THIS_DEVICE)) 64 local device = luup.devices[THIS_DEVICE] 65 66 -- Set our device IP number 67 if (device.ip == "") then 68 return false, "IP Address attribute must be configured", "rfxcom" 69 end 70 ipAddress = device.ip 71 72 -- Get defined read and write port. If not set, set the default port numbers 10001 and 10002 73 local portList = luup.variable_get("urn:upnp-esweb-nl:serviceId:rfxcom1", "portRead", lul_device) 74 if ((portList or "") == "") then 75 portList = "10001" 76 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "portRead", portList, lul_device) 77 elseif (portList:find("%d") == nil) then 78 return false, "The Port Read parameter must be of the form nnnn. eg. 10001" 79 end 80 ipPortRead = portList 81 82 local portList = luup.variable_get("urn:upnp-esweb-nl:serviceId:rfxcom1", "portWrite", lul_device) 83 if ((portList or "") == "") then 84 portList = "10002" 85 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "portWrite", portList, lul_device) 86 elseif (portList:find("%d") == nil) then 87 return false, "The Port Write parameter must be of the form nnnn. eg. 10002" 88 end 89 ipPortSend = portList 90 91 -- Check if we should create the devices automaticly 92 local RFXAutoCreate = luup.variable_get("urn:upnp-esweb-nl:serviceId:rfxcom1", "AutoCreate", lul_device) 93 if ((RFXAutoCreate or "") == "") then 94 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "AutoCreate", "0", lul_device) 95 end 96 97 -- Check all devices if they are childeren. If so, register in 98 -- the correct array based on the device type 99 for k, v in pairs(luup.devices) do 100 -- Look for devices with this device as parent 101 if (v.device_num_parent == lul_device) then 102 luup.log( "Found child device, lets save! id " .. tostring(v.id) .. " device " .. tostring(v.device_type)) 103 104 -- Check on door sensors 105 if (tostring(v.device_type) == "urn:schemas-micasaverde-com:device:DoorSensor:1") then 106 RFXCountDS = RFXCountDS + 1 107 RFXDevicesDS[RFXCountDS] = v.id 108 end 109 110 -- Check on motion sensors 111 if (tostring(v.device_type) == "urn:schemas-micasaverde-com:device:MotionSensor:1") then 112 RFXCountMS = RFXCountMS + 1 113 RFXDevicesMS[RFXCountMS] = v.id 114 end 115 116 -- Check on keyfobs 117 if (tostring(v.device_type) == "urn:schemas-esweb-nl:device:RFXKeyfob:1") then 118 RFXCountKF = RFXCountKF + 1 119 RFXDevicesKF[RFXCountKF] = v.id 120 end 121 122 -- Check on light switches 123 if (tostring(v.device_type) == "urn:schemas-upnp-org:device:BinaryLight:1") then 124 RFXCountLS = RFXCountLS + 1 125 RFXDevicesLS[RFXCountLS] = v.id 126 end 127 128 -- Check on Harrison window coverings 129 if (tostring(v.device_type) == "urn:schemas-micasaverde-com:device:WindowCovering:1") then 130 RFXCOM_HAR_Count = RFXCOM_HAR_Count + 1 131 RFXCOM_HAR_Devices[RFXCOM_HAR_Count] = v.id 132 end 133 end 134 end 135 luup.log("Tree with number child devices:") 136 luup.log(" door sensors: " .. RFXCountDS) 137 luup.log(" motion sensors: " .. RFXCountMS) 138 luup.log(" keyfob sensors: " .. RFXCountKF) 139 luup.log(" light switches: " .. RFXCountLS) 140 luup.log(" window covering: " .. RFXCOM_HAR_Count) 141 142 luup.log("Open socket for read " .. ipAddress .. " port " .. ipPortRead ) 143 luup.io.open(THIS_DEVICE, ipAddress, ipPortRead) 144 startupReady = 1 145 146 luup.log("Startup RFXCOM ready") 147 148 return true, "ok", "rfxcom" 74 149 end 75 76 77 function SendHarrisonCmd( psHouse, psCmd) 78 local liMODEHAR = 0x34 79 80 --luup.log("Connect to rfxtrans ip " .. ipAddress .. " port " .. ipPortSend) 81 82 local client = socket.connect(ipAddress, ipPortSend) 83 client:settimeout(2) 84 85 --to send a command we need to specify: F0 CMD F0 CMD where CMD has special meaning. 86 local lsSend = string.char(0xf0) .. string.char(liMODEHAR) .. string.char(0xf0) .. string.char(liMODEHAR) 87 --luup.log("send cmd: " .. formattohex(lsSend)) 88 89 local lsSendStat = client:send(lsSend) 90 --luup.log("send cmd result: " .. formattohex(lsSendStat)) 91 92 -- We will receive an ack with the last byte of the command sent. or a nack 0x5a 93 local lsRecvStat=client:receive(1) 94 --luup.log("recv result: " .. formattohex(lsRecvStat)) 95 96 --to send a command we need to specify: [House Code][Command] 97 -- House code is 2 bytes. Open up the remote. There are 8 dip switches with a 3 state. 98 -- note down the bits where state top = 2 bits: 11, middle = 10, down = 00. 99 -- write down the bits starting from switch 1 to 8. 100 -- I get the following code of bits: 00 00 11 11 00 10 10 10 101 -- This is binary and can be written in hex as follows: 0F2A and there you have the house code 102 -- The curtain has three command: open, close, stop: F380, CF80 and FC80 103 -- 104 if ( psCmd == "OPEN" ) then 105 lsSend = psHouse .. "F380" 106 107 luup.log("send open command for Harrison house code: " .. psHouse) 108 elseif ( psCmd == "CLOSE") then 109 lsSend = psHouse .. "CF80" 110 111 luup.log("send close command for Harrison house code: " .. psHouse) 112 else 113 --stop 114 lsSend = psHouse .. "FC80" 115 116 luup.log("send stop command for Harrison house code: " .. psHouse) 117 end 118 119 lsSend = ToByteString( lsSend ) 120 121 local lsSendStat = client:send(lsSend) 122 --luup.log("send cmd result: " .. formattohex(lsSendStat)) 123 124 -- We will recieve an ack with the last byte. or a nack 0x5a 125 local lsRecvStat=client:receive(1) 126 --luup.log("recv result: " .. formattohex(lsRecvStat)) 127 128 client:close() 129 --luup.log("finished: ") 130 end 131 150 132 151 function ToByteString( psHexString) 133 152 local resultstr = "" 134 153 135 154 if ( psHexString ~= nil ) then 136 137 138 139 155 for teller = 1, string.len(psHexString), 2 do 156 local lsHex = string.sub(psHexString, teller, teller+1) 157 resultstr = resultstr .. string.char( tonumber( lsHex, 16) ) 158 end 140 159 end 141 160 … … 147 166 148 167 if ( dataBuf ~= nil ) then 149 150 151 168 for teller = 1, string.len(dataBuf) do 169 resultstr = resultstr .. string.format("%02X ", string.byte(dataBuf, teller) ) 170 end 152 171 end 153 172 … … 155 174 end 156 175 157 158 176 --Helper function to get a substring that can handle null chars 159 177 function GetStringPart( psString, piStart, piLen ) 160 161 162 163 164 165 166 167 168 169 170 171 172 178 local lsResult = "" 179 180 if ( psString ~= nil ) then 181 local liStringLength = 1 + #psString 182 for teller = piStart, (piStart + piLen - 1) do 183 -- if not beyond string length 184 if ( liStringLength > teller ) then 185 lsResult = lsResult .. string.sub(psString, teller, teller) 186 end 187 end 188 end 189 190 return lsResult 173 191 end 174 175 176 function ProcessMessage( psCommand ) 177 local lsRFXMSG = "" 178 179 while ( #RFXmsgTable > 0 ) do 180 181 psCommand = table.remove( RFXmsgTable, 1) 182 --luup.log("Process Msg : " .. formattohex(psCommand)) 183 184 local liBitLength = bitw.band( string.byte(psCommand, 1), 0x7f) 185 psCommand = GetStringPart( psCommand, 2, string.len( psCommand ) -1 ) 186 local liCommandLength = string.len(psCommand) 187 188 if ( liCommandLength == 4 ) then 189 --luup.log("trying x10") 190 --luup.log("Process Msg : " .. formattohex(psCommand)) 191 -- 70 8F 00 FF 192 193 if ( bitw.bxor( string.byte(psCommand, 1) , string.byte(psCommand, 2) ) == 0xff ) then 194 if ( bitw.bxor( string.byte(psCommand, 3) , string.byte(psCommand, 4) ) == 0xff ) then 195 196 local lsX10Coding = "MNOPCDABEFGHKLIJ" 197 local lsX10Message = string.char( string.byte( lsX10Coding, 1 + bitw.rshift( bitw.band( string.byte(psCommand, 1), 0xf0) , 4 ) ) ) 198 199 local liCommand = string.byte(psCommand, 3) 200 if ( liCommand == 0x80 ) then 201 lsX10Message = lsX10Message .. "-All lights off" 202 elseif ( liCommand == 0x90 ) then 203 lsX10Message = lsX10Message .. "-All lights on" 204 elseif ( liCommand == 0x88 ) then 205 lsX10Message = lsX10Message .. "-Bright" 206 elseif ( liCommand == 0x98 ) then 207 lsX10Message = lsX10Message .. "-Dim" 208 else 209 local liRecBytes = bitw.rshift( bitw.band( string.byte(psCommand, 3) , 0x10), 4) 210 liRecBytes = liRecBytes + bitw.rshift( bitw.band( string.byte(psCommand, 3) , 0x8), 2) 211 liRecBytes = liRecBytes + bitw.rshift( bitw.band( string.byte(psCommand, 3) , 0x40), 4) 212 liRecBytes = liRecBytes + bitw.lshift( bitw.band( string.byte(psCommand, 3) , 0x4), 1) 213 liRecBytes = liRecBytes + 1 214 215 lsX10Message = lsX10Message .. string.format("%02X", liRecBytes) 216 if ( bitw.band( string.byte(psCommand, 3) , 0x1) == 1) then 217 lsX10Message = lsX10Message .. "-Prog Koppla (non X10)" 218 elseif ( bitw.band( string.byte(psCommand, 3) , 0x20) == 0) then 219 lsX10Message = lsX10Message .. "-On" 220 else 221 lsX10Message = lsX10Message .. "-Off" 222 end 223 end 224 225 lsRFXMSG = string.format ("[X10: %s]", lsX10Message) 226 end 227 end 228 end 229 230 if ( liCommandLength == 5 ) then 231 --luup.log("Process homeeasy Msg : " .. formattohex(psCommand) ) 232 --example: 03 A1 C2 9B 80 233 234 --bits 6 5 235 local lnDataM = bitw.rshift( bitw.band( string.byte(psCommand, 4) , 0x30 ), 4 ) 236 237 --bits 4 3 2 1 238 local lnDataU = bitw.band( string.byte(psCommand, 4) , 0x0f ) 239 240 --bits 8 7 6 5 241 local lnDataP = bitw.rshift( bitw.band( string.byte(psCommand, 5) , 0xf0 ), 4 ) 242 243 --bits 4 3 244 local lnDataI = bitw.rshift( bitw.band( string.byte(psCommand, 5) , 0x0c ), 2 ) 245 246 local lsDevice = string.format("%02X", bitw.rshift(string.byte(psCommand, 1), 6) ) 247 lsDevice = lsDevice .. string.format("%02X", bitw.bor( bitw.lshift( bitw.band(string.byte(psCommand, 1), 0x3f), 2 ), bitw.rshift(string.byte(psCommand, 2), 6))) 248 lsDevice = lsDevice .. string.format("%02X", bitw.bor( bitw.lshift( bitw.band(string.byte(psCommand, 2), 0x3f), 2 ), bitw.rshift(string.byte(psCommand, 3), 6))) 249 lsDevice = lsDevice .. string.format("%02X", bitw.bor( bitw.lshift( bitw.band(string.byte(psCommand, 3), 0x3f), 2 ), bitw.rshift(string.byte(psCommand, 4), 6))) 250 251 local lsHECmd = "" 252 253 if (lnDataM == 0) then lsHECmd = "off" end 254 if (lnDataM == 1) then lsHECmd = "on" end 255 if (lnDataM == 2) then lsHECmd = "group off" end 256 if (lnDataM == 3) then lsHECmd = "group on" end 257 258 lsRFXMSG = string.format ("[HOMEEASY: Device: %s Unit: %d Command: %s ( p: %d i: %d )]", lsDevice, lnDataU, lsHECmd, lnDataP, lnDataI) 259 260 end 261 262 if ( liCommandLength == 11 ) then 263 --luup.log("trying oregon WGR918") 264 265 if ( ( string.byte(psCommand, 1) == 0x3a ) and ( string.byte(psCommand, 2) == 0x0d ) ) then 266 267 local liDataDir = string.byte(psCommand, 6) * 10 + bitw.rshift(string.byte(psCommand, 5), 4) 268 local lnDataSpeed = bitw.band( string.byte(psCommand, 8) , 0x0f) * 10 + (string.byte(psCommand, 7) / 10 ) 269 local lnDataSpeedav = string.byte(psCommand, 9) + ( bitw.rshift( string.byte(psCommand, 8), 4) / 10) 270 271 local lsDevice = string.format("%02X", string.byte(psCommand, 4) ) 272 273 lsRFXMSG = string.format("[OREGONWGR918: WIND3 Device: %s Direction: %3d Speed: %5.2f Speed av: %5.2f]", lsDevice, liDataDir, lnDataSpeed, lnDataSpeedav) 274 275 end 276 end 277 278 if ( string.len( lsRFXMSG ) == 0 ) then 279 luup.log("Unknown Msg : " .. formattohex(psCommand) ) 280 else 281 -- ignore repeated messages. 282 if ( RFXLastMsg ~= lsRFXMSG ) then 283 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "Message", lsRFXMSG, THIS_DEVICE) 284 luup.log( lsRFXMSG ) 285 286 end 287 end 288 289 RFXLastMsg = lsRFXMSG 290 291 end 292 192 193 function SendHarrisonCmd( psHouse, psCmd) 194 local liMODEHAR = 0x34 195 local liMODERFXCOM = 0x33 196 local client = nil 197 local lsSend = "" 198 local lsSendStat = "" 199 local lsRecvStat = "" 200 201 luup.log("Connect to rfxtrans ip " .. ipAddress .. " port " .. ipPortSend) 202 client = socket.connect(ipAddress, ipPortSend) 203 204 if client ~= nil then 205 client:settimeout(2) 206 207 luup.log("Send cmd " .. psCmd .. " to " .. psID) 208 209 --to send a command we need to specify: F0 CMD F0 CMD where CMD has special meaning. 210 lsSend = string.char(0xf0) .. string.char(liMODEHAR) .. string.char(0xf0) .. string.char(liMODEHAR) 211 --luup.log("send cmd: " .. formattohex(lsSend)) 212 213 lsSendStat = client:send(lsSend) 214 --luup.log("send cmd result: " .. formattohex(lsSendStat)) 215 216 -- We will receive an ack with the last byte of the command sent. or a nack 0x5a 217 lsRecvStat=client:receive(1) 218 --luup.log("recv result: " .. formattohex(lsRecvStat)) 219 220 --to send a command we need to specify: [House Code][Command] 221 -- House code is 2 bytes. Open up the remote. There are 8 dip switches with a 3 state. 222 -- note down the bits where state top = 2 bits: 11, middle = 10, down = 00. 223 -- write down the bits starting from switch 1 to 8. 224 -- I get the following code of bits: 00 00 11 11 00 10 10 10 225 -- This is binary and can be written in hex as follows: 0F2A and there you have the house code 226 -- The curtain has three command: open, close, stop: F380, CF80 and FC80 227 -- 228 if ( psCmd == "OPEN" ) then 229 lsSend = psHouse .. "F380" 230 luup.log("send open command for Harrison house code: " .. psHouse) 231 elseif ( psCmd == "CLOSE") then 232 lsSend = psHouse .. "CF80" 233 luup.log("send close command for Harrison house code: " .. psHouse) 234 else 235 --stop 236 lsSend = psHouse .. "FC80" 237 luup.log("send stop command for Harrison house code: " .. psHouse) 238 end 239 240 lsSend = ToByteString( lsSend ) 241 242 local lsSendStat = client:send(lsSend) 243 --luup.log("send cmd result: " .. formattohex(lsSendStat)) 244 245 -- We will recieve an ack with the last byte. or a nack 0x5a 246 local lsRecvStat=client:receive(1) 247 --luup.log("recv result: " .. formattohex(lsRecvStat)) 248 249 -- Close client connection 250 client:close() 251 else 252 return false 253 end 254 luup.log("finished: ") 255 end 256 257 function SendCmd( psID, psCmd ) 258 local liMODEHAR = 0x34 259 local liMODERFXCOM = 0x33 260 local client = nil 261 local lsSend = "" 262 local lsSendStat = "" 263 local lsRecvStat = "" 264 265 266 luup.log("Connect to rfxtrans ip " .. ipAddress .. " port " .. ipPortSend) 267 client = socket.connect(ipAddress, ipPortSend) 268 269 if client ~= nil then 270 client:settimeout(2) 271 272 luup.log("Send cmd " .. psCmd .. " to " .. psID) 273 274 --to send a command we need to specify: F0 CMD F0 CMD where CMD has special meaning. 275 lsSend = string.char(0xf0) .. string.char(liMODERFXCOM) .. string.char(0xf0) .. string.char(liMODERFXCOM) 276 if lsSend ~= nil then luup.log("send cmd: " .. formattohex(lsSend)) end 277 278 lsSendStat = client:send(lsSend) 279 if lsSendStat ~= nil then luup.log("send cmd result: " .. formattohex(lsSendStat)) end 280 281 -- We will receive an ack with the last byte of the command sent. or a nack 0x5a 282 lsRecvStat=client:receive(1) 283 if lsRecvStat ~= nil then luup.log("recv result: " .. formattohex(lsRecvStat)) end 284 285 -- Because this is a homeeasy, kaku device, calc the 286 -- command to be send based on the ID of the device 287 288 local psByteID = ToByteString(psID) 289 local liBitLength = bitw.band( string.byte(psByteID, 1), 0x7f) 290 luup.log("Bit length is " .. liBitLength .. " based on id " .. psID) 291 292 if liBitLength == 33 then 293 lsSend = RecodeHomeEasy33(psByteID,psCmd) 294 elseif liBitLength == 34 then 295 lsSend = RecodeHomeEasy34(psByteID,psCmd) 296 elseif liBitLength == 36 then 297 lsSend = RecodeHomeEasy36(psByteID,psCmd) 298 elseif liBitLength == 37 then 299 lsSend = RecodeHomeEasy37(psByteID,psCmd) 300 else 301 lsSend = nil 302 end 303 304 if lsSend ~= nil then 305 lsSend = ToByteString(lsSend) 306 luup.log("send command " .. psCmd .. " as " .. formattohex(lsSend)) 307 308 lsSendStat = client:send(lsSend) 309 if lsSendStat ~= nil then luup.log("send cmd result: " .. formattohex(lsSendStat)) end 310 311 -- We will recieve an ack with the last byte. or a nack 0x5a 312 lsRecvStat=client:receive(1) 313 if lsRecvStat ~= nil then luup.log("recv result: " .. formattohex(lsRecvStat)) end 314 end 315 316 -- Close client connection 317 client:close() 318 else 319 return false 320 end 321 luup.log("finished: ") 322 end 323 324 function RecodeHomeEasy33(psID,psCmd) 325 local lbCmd = string.byte(psID, 5) 326 327 if psCmd == RFXConstants.cmdOff then 328 lbCmd = bitw.bor(lbCmd,0x00) 329 elseif psCmd == RFXConstants.cmdOn then 330 lbCmd = bitw.bor(lbCmd,0x10) 331 elseif psCmd == RFXConstants.cmdGroupOff then 332 lbCmd = bitw.bor(lbCmd,0x20) 333 elseif psCmd == RFXConstants.cmdGroupOn then 334 lbCmd = bitw.bor(lbCmd,0x30) 335 end 336 337 return string.format("%02x%02x%02x%02x%02x%02x",string.byte(psID, 1),string.byte(psID, 2),string.byte(psID, 3), 338 string.byte(psID, 4),lbCmd, string.byte(psID, 6)) 339 end 340 341 function RecodeHomeEasy34(psID,psCmd) 342 local lbCmd = string.byte(psID, 5) 343 344 luup.log("Recode homeeasy 34 cmd " .. string.format("%02x",lbCmd)) 345 if psCmd == RFXConstants.cmdOff then 346 lbCmd = bitw.bor(lbCmd,0x00) 347 elseif psCmd == RFXConstants.cmdOn then 348 lbCmd = bitw.bor(lbCmd,0x10) 349 elseif psCmd == RFXConstants.cmdGroupOff then 350 lbCmd = bitw.bor(lbCmd,0x20) 351 elseif psCmd == RFXConstants.cmdGroupOn then 352 lbCmd = bitw.bor(lbCmd,0x30) 353 end 354 355 return string.format("21%02x%02x%02x%02x%02x",string.byte(psID, 2),string.byte(psID, 3), 356 string.byte(psID, 4),lbCmd, string.byte(psID, 6)) 357 end 358 359 function RecodeHomeEasy36(psID,psCmd) 360 return nil 361 end 362 363 ------------------------------------------------------------------------------------ 364 -- decode X10 commands 365 ------------------------------------------------------------------------------------ 366 function decodeX10(psCommand) 367 local liCommandLength = string.len(psCommand) 368 local lsRFXMSG = "" 369 370 if ( liCommandLength == 4 ) then 371 luup.log("trying x10") 372 luup.log("decode msg : " .. formattohex(psCommand)) 373 -- 70 8F 00 FF 374 375 if ( bitw.bxor( string.byte(psCommand, 1) , string.byte(psCommand, 2) ) == 0xff ) then 376 if ( bitw.bxor( string.byte(psCommand, 3) , string.byte(psCommand, 4) ) == 0xff ) then 377 378 local lsX10Coding = "MNOPCDABEFGHKLIJ" 379 local lsX10Message = string.char( string.byte( lsX10Coding, 1 + bitw.rshift( bitw.band( string.byte(psCommand, 1), 0xf0) , 4 ) ) ) 380 381 local liCommand = string.byte(psCommand, 3) 382 if ( liCommand == 0x80 ) then 383 lsX10Message = lsX10Message .. "-All lights off" 384 elseif ( liCommand == 0x90 ) then 385 lsX10Message = lsX10Message .. "-All lights on" 386 elseif ( liCommand == 0x88 ) then 387 lsX10Message = lsX10Message .. "-Bright" 388 elseif ( liCommand == 0x98 ) then 389 lsX10Message = lsX10Message .. "-Dim" 390 else 391 local liRecBytes = bitw.rshift( bitw.band( string.byte(psCommand, 3) , 0x10), 4) 392 liRecBytes = liRecBytes + bitw.rshift( bitw.band( string.byte(psCommand, 3) , 0x8), 2) 393 liRecBytes = liRecBytes + bitw.rshift( bitw.band( string.byte(psCommand, 3) , 0x40), 4) 394 liRecBytes = liRecBytes + bitw.lshift( bitw.band( string.byte(psCommand, 3) , 0x4), 1) 395 liRecBytes = liRecBytes + 1 396 397 lsX10Message = lsX10Message .. string.format("%02X", liRecBytes) 398 if ( bitw.band( string.byte(psCommand, 3) , 0x1) == 1) then 399 lsX10Message = lsX10Message .. "-Prog Koppla (non X10)" 400 elseif ( bitw.band( string.byte(psCommand, 3) , 0x20) == 0) then 401 lsX10Message = lsX10Message .. "-On" 402 else 403 lsX10Message = lsX10Message .. "-Off" 404 end 405 end 406 407 lsRFXMSG = string.format ("[X10: %s]", lsX10Message) 408 end 409 end 410 end 411 412 return lsRFXMSG 413 end 414 415 ------------------------------------------------------------------------------------ 416 -- decode homeeasy / kaku commands 417 ------------------------------------------------------------------------------------ 418 function decodeHomeEasy36(psCommand) 419 local lsSensorManufacturer = RFXConstants.sensorManufacturerHomeEasy 420 local lsSensorType = RFXConstants.sensorTypeControler 421 local lsID = "" 422 local lsCmd = "" 423 424 -- Make ID as received bytes minus command 425 -- This is not the real ID...just a quick way to send back to RFX 426 -- what we received 427 lsID = string.format("%02X%02X%02X%02X%02X%02X",string.byte(psCommand, 1),string.byte(psCommand, 2),string.byte(psCommand, 3), 428 string.byte(psCommand, 4),bitw.band(string.byte(psCommand, 5),0xCF),string.byte(psCommand, 6)) 429 430 -- Extract on/off/group on/group off command 431 local lnDataM = bitw.rshift( bitw.band( string.byte(psCommand, 5) , 0x30 ), 4 ) 432 if (lnDataM == 0) then lsCmd = RFXConstants.cmdOff end 433 if (lnDataM == 1) then lsCmd = RFXConstants.cmdOn end 434 if (lnDataM == 2) then lsCmd = RFXConstants.cmdGroupOff end 435 if (lnDataM == 3) then lsCmd = RFXConstants.cmdGroupOn end 436 437 -- Make message 438 lsRFXMSG = string.format ("[%s:%s ID: %s CMD: %d]", lsSensorManufacturer,lsSensorType, lsID, lsCmd) 439 440 return lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer 441 end 442 443 function decodeHomeEasy34(psCommand) 444 local lsSensorManufacturer = RFXConstants.sensorManufacturerHomeEasy 445 local lsSensorType = RFXConstants.sensorTypeControler 446 local lsID = "" 447 local lsCmd = "" 448 449 lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer = decodeHomeEasy36(psCommand) 450 return lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer 451 end 452 453 ------------------------------------------------------------------------------------ 454 -- decode Visonic commands 455 ------------------------------------------------------------------------------------ 456 function decodeVisonic( psCommand ) 457 local lsRFXMSG = "" 458 local liCommandLength = string.len(psCommand) 459 local lsSensorType = "" 460 local lsSensorManufacturer = RFXConstants.sensorManufacturerVisonic 461 local lsCmd = "" 462 463 -- First decode ID 464 local lsID = string.format("%02X%02X%02X-%d",string.byte(psCommand, 2),string.byte(psCommand, 3),string.byte(psCommand, 6),string.byte(psCommand,2) * 256 + string.byte(psCommand,3)) 465 local liHsAddr = 0 466 --liHsAddr = createhsaddr(psCommand) 467 468 --if protocol = MODEB32 then 469 -- lsRFXMSG = string.format(" addr: %02x%d",string.byte(psCommand, 2),liHsAddr) 470 --else 471 -- lsRFXMSG = string.format(" addr: %s ID: %d,lsDevice,liHsAddr) 472 --end 473 474 -- Next decode message data 475 if string.byte(psCommand, 4) == 0x44 then 476 lsSensorType = RFXConstants.sensorTypeDoor 477 lsCmd = RFXConstants.cmdAlert + RFXConstants.cmdTamper 478 elseif string.byte(psCommand, 4) == 0xC4 then 479 lsSensorType = RFXConstants.sensorTypeDoor 480 lsCmd = RFXConstants.cmdNormal + RFXConstants.cmdTamper 481 elseif string.byte(psCommand, 4) == 0x4 then 482 lsSensorType = RFXConstants.sensorTypeDoor 483 lsCmd = RFXConstants.cmdAlert 484 elseif string.byte(psCommand, 4) == 0x5 then 485 lsSensorType = RFXConstants.sensorTypeDoor 486 lsCmd = RFXConstants.cmdAlert + RFXConstants.cmdBatteryLow 487 elseif string.byte(psCommand, 4) == 0x84 then 488 lsSensorType = RFXConstants.sensorTypeDoor 489 lsCmd = RFXConstants.cmdNormal 490 elseif string.byte(psCommand, 4) == 0x85 then 491 lsSensorType = RFXConstants.sensorTypeDoor 492 lsCmd = RFXConstants.cmdNormal + RFXConstants.cmdBatteryLow 493 elseif string.byte(psCommand, 4) == 0x4C then 494 lsSensorType = RFXConstants.sensorTypeMotion 495 lsCmd = RFXConstants.cmdAlert + RFXConstants.cmdTamper 496 elseif string.byte(psCommand, 4) == 0xCC then 497 lsSensorType = RFXConstants.sensorTypeMotion 498 lsCmd = RFXConstants.cmdNormal + RFXConstants.cmdTamper 499 elseif string.byte(psCommand, 4) == 0x0C then 500 lsSensorType = RFXConstants.sensorTypeMotion 501 lsCmd = RFXConstants.cmdAlert 502 elseif string.byte(psCommand, 4) == 0x0D then 503 lsSensorType = RFXConstants.sensorTypeMotion 504 lsCmd = RFXConstants.cmdAlert + RFXConstants.cmdBatteryLow 505 elseif string.byte(psCommand, 4) == 0x8C then 506 lsSensorType = RFXConstants.sensorTypeMotion 507 lsCmd = RFXConstants.cmdNormal 508 elseif string.byte(psCommand, 4) == 0x8D then 509 lsSensorType = RFXConstants.sensorTypeMotion 510 lsCmd = RFXConstants.cmdNormal + RFXConstants.cmdBatteryLow 511 elseif string.byte(psCommand, 4) == 0xE0 then 512 if string.byte(psCommand, 2) == 0xff then 513 lsCmd = RFXConstants.cmdJamming -- Master receiver jamming detected 514 elseif string.byte(psCommand, 2) == 0x0 then 515 lsCmd = RFXConstants.cmdJamming -- Slave receiver jamming detected 516 else 517 -- Unknown data packet received 518 end 519 elseif string.byte(psCommand, 4) == 0xF8 then 520 if string.byte(psCommand, 2) == 0xff then 521 lsCmd = RFXConstants.cmdJamming -- Master receiver jamming detected 522 elseif string.byte(psCommand, 2) == 0x0 then 523 lsCmd = RFXConstants.cmdJamming -- Slave receiver jamming detected 524 else 525 -- Unknown command 526 end 527 elseif string.byte(psCommand, 4) == 0x2 then 528 lsSensorType = RFXConstants.sensorTypeKeyFob 529 lsCmd = RFXConstants.cmdArmAway 530 elseif string.byte(psCommand, 4) == 0xE then 531 lsSensorType = RFXConstants.sensorTypeKeyFob 532 lsCmd = RFXConstants.cmdArmHome 533 elseif string.byte(psCommand, 4) == 0x22 then 534 lsSensorType = RFXConstants.sensorTypeKeyFob 535 lsCmd = RFXConstants.cmdPanic 536 elseif string.byte(psCommand, 4) == 0x42 then 537 lsSensorType = RFXConstants.sensorTypeKeyFob 538 lsCmd = RFXConstants.cmdGroupOn 539 elseif string.byte(psCommand, 4) == 0x82 then 540 lsSensorType = RFXConstants.sensorTypeKeyFob 541 lsCmd = RFXConstants.cmdDisarm 542 else 543 -- Unknown data packet received 544 end 545 546 -- Create RFXMSG text 547 lsRFXMSG = string.format ("[%s:%s ID: %s CMD: %d]", lsSensorManufacturer,lsSensorType, lsID, lsCmd) 548 549 return lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer 550 end 551 552 553 function createhsaddr(psCommand) 554 local liHsAddr = 0 555 556 if bitw.band(string.byte(psCommand, 1),0x1) ~= 0 then 557 liHsAddr = bitw.bor(liHsAddr,0x80) 558 end 559 if bitw.band(string.byte(psCommand, 1),0x2) ~= 0 then 560 liHsAddr = bitw.bor(liHsAddr,0x40) 561 end 562 if bitw.band(string.byte(psCommand, 1),0x4) ~= 0 then 563 liHsAddr = bitw.bor(liHsAddr,0x20) 564 end 565 if bitw.band(string.byte(psCommand, 1),0x8) ~= 0 then 566 liHsAddr = bitw.bor(liHsAddr,0x10) 567 end 568 if bitw.band(string.byte(psCommand, 1),0x10) ~= 0 then 569 liHsAddr = bitw.bor(liHsAddr,0x8) 570 end 571 if bitw.band(string.byte(psCommand, 1),0x20) ~= 0 then 572 liHsAddr = bitw.bor(liHsAddr,0x4) 573 end 574 if bitw.band(string.byte(psCommand, 1),0x40) ~= 0 then 575 liHsAddr = bitw.bor(liHsAddr,0x2) 576 end 577 if bitw.band(string.byte(psCommand, 1),0x80) ~= 0 then 578 liHsAddr = bitw.bor(liHsAddr,0x1) 579 end 580 if bitw.band(string.byte(psCommand, 2),0x1) ~= 0 then 581 liHsAddr = bitw.bor(liHsAddr,0x8000) 582 end 583 if bitw.band(string.byte(psCommand, 2),0x2) ~= 0 then 584 liHsAddr = bitw.bor(liHsAddr,0x4000) 585 end 586 if bitw.band(string.byte(psCommand, 2),0x4) ~= 0 then 587 liHsAddr = bitw.bor(liHsAddr,0x2000) 588 end 589 if bitw.band(string.byte(psCommand, 2),0x8) ~= 0 then 590 liHsAddr = bitw.bor(liHsAddr,0x1000) 591 end 592 if bitw.band(string.byte(psCommand, 2),0x10) ~= 0 then 593 liHsAddr = bitw.bor(liHsAddr,0x800) 594 end 595 if bitw.band(string.byte(psCommand, 2),0x20) ~= 0 then 596 liHsAddr = bitw.bor(liHsAddr,0x400) 597 end 598 if bitw.band(string.byte(psCommand, 2),0x40) ~= 0 then 599 liHsAddr = bitw.bor(liHsAddr,0x200) 600 end 601 if bitw.band(string.byte(psCommand, 2),0x80) ~= 0 then 602 liHsAddr = bitw.bor(liHsAddr,0x100) 603 end 604 605 return liHsAddr 606 end 607 608 function decodex(psCommand) 609 local lsRFXMSG = "" 610 local lsSensorType = "" 611 local lsID = "" 612 local lsCmd = "" 613 local lsSensorManufacturer = "" 614 local liBitLength = bitw.band( string.byte(psCommand, 1), 0x7f) 615 616 if (bitw.bxor( string.byte(psCommand, 2) , string.byte(psCommand, 3) ) == 0xff and string.byte(psCommand, 2) == 0xee) then 617 luup.log("decoderfremote()") 618 end 619 if (string.byte(psCommand, 3) == 0 and (bitw.band(string.byte(psCommand, 4),0x0f) == 0)) then 620 luup.log("decodeatiplus()") 621 end 622 if bitw.bxor(string.byte(psCommand, 2),string.byte(psCommand, 3)) == 0xff and bitw.bxor(string.byte(psCommand, 4),string.byte(psCommand, 5)) == 0xff and liBitLength == 32 then 623 luup.log("decodex10()") 624 end 625 if liBitLength == 32 and bitw.bxor(string.byte(psCommand, 2),string.byte(psCommand, 3)) == 0xfe and bitw.bxor(string.byte(psCommand, 4),string.byte(psCommand, 5)) == 0xff then 626 luup.log("decodedm10()") 627 end 628 if string.byte(psCommand, 2) == (bitw.band(string.byte(psCommand, 3),0xf0) + (0x0f - bitw.band(string.byte(psCommand, 3),0x0f))) and bitw.bxor(string.byte(psCommand, 4),string.byte(psCommand, 5)) == 0xff then 629 luup.log("decodex10security()") 630 end 631 if (bitw.bxor(string.byte(psCommand, 4),string.byte(psCommand, 5)) == 0xff) then 632 lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer = decodeVisonic(psCommand) 633 end 634 635 return lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer 293 636 end 294 295 -- The call back function to processthe buffer.637 638 -- The call back function to decode the buffer. 296 639 function endOfData( withdata ) 297 640 298 -- Now loop the buffer and split into messages to process.299 641 -- Now loop the buffer and split into messages to decode. 642 local liCount = 0 300 643 301 644 while ( #buffer > 0 ) do 302 645 303 --luup.log("endOfData buffer : " .. tostring(liCount) .. " : " .. formattohex(buffer))304 646 luup.log("endOfData buffer : " .. tostring(liCount) .. " : " .. formattohex(buffer)) 647 liCount = liCount + 1 305 648 306 649 -- we have data, first byte has length and a flag in the first bit to signal if from master or slave function of rfxcom 307 -- we are not interested in the flag so strip. Length is in bits so divide by 8 using right shift 3 308 local liPacketLength = bitw.rshift( bitw.band( string.byte(buffer, 1), 0x7f), 3) 309 310 -- We now have the length in bytes but the remainder of the division was lost. 311 -- Last three bits had the remainder, if these contain any data then add one byte 312 if ( bitw.band( string.byte(buffer, 1), 0x07) > 0 ) then 313 liPacketLength = liPacketLength + 1 314 end 315 316 -- Now isolate message from buffer and shrink buffer accordingly 317 -- Unfortunately the string.sub function cannot handle null chars 318 local lsCommand = GetStringPart( buffer, 1, 1 + liPacketLength ) 319 buffer = GetStringPart( buffer, liPacketLength + 2, #buffer) 320 321 -- Log found message and process!! 322 if ( lsCommand ~= nil and #lsCommand > 0 ) then 323 table.insert( RFXmsgTable, lsCommand ) 324 luup.call_delay("ProcessMessage", 0 , "none") 325 end 650 -- we are not interested in the flag so strip. Length is in bits so divide by 8 using right shift 3 651 local liPacketLength = bitw.rshift( bitw.band( string.byte(buffer, 1), 0x7f), 3) 652 653 -- We now have the length in bytes but the remainder of the division was lost. 654 -- Last three bits had the remainder, if these contain any data then add one byte 655 if ( bitw.band( string.byte(buffer, 1), 0x07) > 0 ) then 656 liPacketLength = liPacketLength + 1 657 end 658 659 -- Now isolate message from buffer and shrink buffer accordingly 660 -- Unfortunately the string.sub function cannot handle null chars 661 local lsCommand = GetStringPart( buffer, 1, 1 + liPacketLength ) 662 buffer = GetStringPart( buffer, liPacketLength + 2, #buffer) 663 664 -- Log found message and decode!! 665 if ( lsCommand ~= nil and #lsCommand > 0 ) then 666 luup.log("RFX message compleet: " .. formattohex(lsCommand)) 667 table.insert( RFXmsgTable, lsCommand ) 668 luup.call_delay("processMessage", 0 , "none") 669 end 326 670 327 671 end 328 672 329 673 -- Okay Lets flag all is okay for the callback 330 674 return 0 331 675 end 676 677 ------------------------------------------------------------------------------------ 678 -- Main routine to decode and process the received messages 679 ------------------------------------------------------------------------------------ 680 function processMessage(psCommand) 681 while ( #RFXmsgTable > 0 ) do 682 local lsRFXMSG = "" 683 local lsSensorType = "" 684 local lsID = "" 685 local lsCmd = "" 686 local lsSensorManufacturer = "" 687 688 psCommand = table.remove( RFXmsgTable, 1) 689 local liBitLength = bitw.band( string.byte(psCommand, 1), 0x7f) 690 691 luup.log(string.format("decodeMessage bits:%d data:%s",liBitLength,formattohex(psCommand))) 692 693 --psCommand = GetStringPart( psCommand, 2, string.len( psCommand ) -1 ) 694 --local liCommandLength = string.len(psCommand) 695 696 -- Decode based on bitlength 697 if liBitLength == 12 then 698 luup.log("decodeHomeEasyHeater12") 699 elseif liBitLength == 13 then 700 luup.log("decodeMertikMaxitrol13") 701 elseif liBitLength == 20 then 702 luup.log("decodeATIRemoteWonder20") 703 elseif liBitLength == 22 then 704 luup.log("decodeRobocamNinja22") 705 elseif liBitLength == 24 then 706 luup.log("decodeArc24") 707 luup.log("decodeWaveman24") 708 elseif liBitLength == 25 then 709 luup.log("decodeHarrison25") 710 elseif liBitLength == 26 then 711 luup.log("decodeIkeaKoppla26") 712 elseif liBitLength == 32 then 713 luup.log("decodeX1032") 714 luup.log("decodeDM1032") 715 luup.log("decodePCRemote32") 716 luup.log("decodeRFXSensor32") 717 elseif liBitLength == 33 then 718 luup.log("decodeHomeEasy33") 719 elseif liBitLength == 34 then 720 lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer = decodeHomeEasy34(psCommand) 721 elseif liBitLength == 36 then 722 lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer = decodeHomeEasy36(psCommand) 723 elseif liBitLength == 37 then 724 luup.log("decodeHomeEasy37") 725 elseif liBitLength == 41 then 726 luup.log("decodeX10Security41") 727 lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer = decodeVisonic(psCommand) 728 elseif liBitLength == 44 then 729 luup.log("decodeDigimaxRTS1044") 730 elseif liBitLength == 47 then 731 luup.log("decodeCheaperTronics47") 732 elseif liBitLength == 56 or liBitLength > 59 then 733 luup.log("decodeoregon") 734 else 735 lsRFXMSG,lsSensorType,lsID,lsCmd,lsSensorManufacturer = decodex(psCommand) 736 end 737 738 if ( string.len( lsRFXMSG ) == 0 ) then 739 luup.log("Unknown Msg : " .. formattohex(psCommand) ) 740 else 741 ------------------------------------------------------------------------------------ 742 -- ignore repeated messages. 743 -- Realy new and decoded messages must be processed. After processing, update 744 -- last message variable 745 ------------------------------------------------------------------------------------ 746 if ( RFXLastMsg ~= lsRFXMSG ) then 747 actOnMessage(lsSensorType,lsID,lsCmd) 748 luup.variable_set("urn:upnp-esweb-nl:serviceId:rfxcom1", "Message", lsRFXMSG, THIS_DEVICE) 749 luup.log( lsRFXMSG ) 750 end 751 end 752 753 RFXLastMsg = lsRFXMSG 754 end 755 end 756 757 758 ------------------------------------------------------------------------ 759 -- Act on decoded message 760 -- 761 -- If variable 'AutoCreate' is set to 1 and a received sensor doens't 762 -- exsist yet, it's created. 763 -- Next execution depends on kind of sensor 764 -- Controler (lightswitch): Status variable is set based on cmdOn or cmdOff 765 -- Motion Sensor: Tripped status is set 766 -- Door Sensor: Tripped status is set 767 -- KeyFox: All door and motion sensors are armed or disarmed 768 ------------------------------------------------------------------------ 769 770 function actOnMessage(lsSensorType,lsID,lsCmd) 771 772 luup.log("Received command " .. lsCmd .. " for " .. lsSensorType .. " with ID " .. lsID) 773 774 -- Check if we can find a device with the decoded ID and ourself as parent 775 local device = findChild(THIS_DEVICE, lsID ) 776 777 -- If we can't find a device and we have autocreate active, setup a new tree with child devices 778 -- and add a new child with the correct type and ID 779 if device == nil and luup.variable_get("urn:upnp-esweb-nl:serviceId:rfxcom1", "AutoCreate", lul_device) == "1" then 780 luup.log( "device not found and autocreate enabled..." ) 781 782 local child_devices = luup.chdev.start(THIS_DEVICE); 783 784 ------------------------------------------------------------------------------------ 785 -- First add all 'old' children to the three 786 -- Start with door sensors 787 ------------------------------------------------------------------------------------ 788 for teller = 1, RFXCountDS do 789 luup.chdev.append(THIS_DEVICE, child_devices, RFXDevicesDS[teller], "RFX DS sensor #" .. RFXDevicesDS[teller] , 790 "urn:schemas-micasaverde-com:device:DoorSensor:1","D_DoorSensor1.xml","","",false) 791 end 792 ------------------------------------------------------------------------------------ 793 -- Next with motion sensors 794 ------------------------------------------------------------------------------------ 795 for teller = 1, RFXCountMS do 796 luup.chdev.append(THIS_DEVICE, child_devices, RFXDevicesMS[teller], "RFX MS sensor #" .. RFXDevicesMS[teller] , 797 "urn:schemas-micasaverde-com:device:MotionSensor:1","D_MotionSensor1.xml","","",false) 798 end 799 ------------------------------------------------------------------------------------ 800 -- Next with keyfobs 801 ------------------------------------------------------------------------------------ 802 for teller = 1, RFXCountKF do 803 luup.chdev.append(THIS_DEVICE, child_devices, RFXDevicesKF[teller], "RFX KF sensor #" .. RFXDevicesKF[teller] , 804 "urn:schemas-ActiveRFID:device:RFIDTransmitter:1","D_RFIDTransmitter.xml","","",false) 805 end 806 ------------------------------------------------------------------------------------ 807 -- Next with light switches 808 ------------------------------------------------------------------------------------ 809 for teller = 1, RFXCountLS do 810 luup.chdev.append(THIS_DEVICE, child_devices, RFXDevicesLS[teller], "RFX LS #" .. RFXDevicesLS[teller] , 811 "urn:schemas-upnp-org:device:BinaryLight:1","D_BinaryLight1.xml","","",false) 812 end 813 ------------------------------------------------------------------------------------ 814 -- Next Harrison window covering 815 ------------------------------------------------------------------------------------ 816 for teller = 1, RFXCOM_HAR_Count do 817 luup.chdev.append(THIS_DEVICE, child_devices, RFXCOM_HAR_Devices[teller], 818 "Harrison #" .. RFXCOM_HAR_Devices[teller] , "urn:schemas-micasaverde-com:device:WindowCovering:1", 819 "D_RFXCOMHarrison.xml","","",false) 820 end 821 822 ------------------------------------------------------------------------------------ 823 -- Now add the new device to the tree depending on the sensor type 824 ------------------------------------------------------------------------------------ 825 826 luup.log("Tree buildup, now add " .. lsID .. " with sensortype " .. lsSensorType) 827 828 ------------------------------------------------------------------------------------ 829 -- Add if doorsensor 830 ------------------------------------------------------------------------------------ 831 if lsSensorType == RFXConstants.sensorTypeDoor then 832 luup.log("CREATING CHILD DEVICE DOOR SENSOR WITH ID " .. lsID) 833 luup.chdev.append(THIS_DEVICE, child_devices, lsID, "RFX DS sensor #" .. lsID , 834 "urn:schemas-micasaverde-com:device:DoorSensor:1","D_DoorSensor1.xml","","",false) 835 RFXCountDS = RFXCountDS + 1 836 RFXDevicesDS[RFXCountDS] = lsID 837 end 838 ------------------------------------------------------------------------------------ 839 -- Add if motionsensor 840 ------------------------------------------------------------------------------------ 841 if lsSensorType == RFXConstants.sensorTypeMotion then 842 luup.log("CREATING CHILD DEVICE MOTION SENSOR WITH ID " .. lsID) 843 luup.chdev.append(THIS_DEVICE, child_devices, lsID, "RFX MS sensor #" .. lsID , 844 "urn:schemas-micasaverde-com:device:MotionSensor:1","D_MotionSensor1.xml","","",false) 845 RFXCountMS = RFXCountMS + 1 846 RFXDevicesMS[RFXCountMS] = lsID 847 end 848 ------------------------------------------------------------------------------------ 849 -- Add if keybof 850 ------------------------------------------------------------------------------------ 851 if lsSensorType == RFXConstants.sensorTypeKeyFob then 852 luup.log("CREATING CHILD DEVICE KEYFOB WITH ID " .. lsID) 853 luup.chdev.append(THIS_DEVICE, child_devices, lsID, "RFX KF sensor #" .. lsID , 854 "urn:schemas-ActiveRFID:device:RFIDTransmitter:1","D_RFIDTransmitter.xml","","",false) 855 RFXCountKF = RFXCountKF + 1 856 RFXDevicesKF[RFXCountKF] = lsID 857 end 858 ------------------------------------------------------------------------------------ 859 -- Add if lightswitch 860 ------------------------------------------------------------------------------------ 861 if lsSensorType == RFXConstants.sensorTypeControler then 862 luup.log("CREATING CHILD DEVICE LIGHT SWITCH WITH ID " .. lsID) 863 luup.chdev.append(THIS_DEVICE, child_devices, lsID, "RFX LS #" .. lsID , 864 "urn:schemas-upnp-org:device:BinaryLight:1","D_BinaryLight1.xml","","",false) 865 RFXCountLS = RFXCountLS + 1 866 RFXDevicesLS[RFXCountLS] = lsID 867 end 868 ------------------------------------------------------------------------------------ 869 -- Add if Harrison window covering 870 ------------------------------------------------------------------------------------ 871 if lsSensorType == RFXConstants.sensorTypeWindowCovering then 872 luup.chdev.append(THIS_DEVICE, child_devices, lsID, "Harrison #" .. lsID , 873 "urn:schemas-micasaverde-com:device:WindowCovering:1","D_RFXCOMHarrison.xml","","",false) 874 RFXCOM_HAR_Count = RFXCOM_HAR_Count + 1 875 RFXCOM_HAR_Devices[RFXCOM_HAR_Count] = lsID 876 end 877 luup.log("Tree buildup with number child devices:") 878 luup.log(" door sensors: " .. RFXCountDS) 879 luup.log(" motion sensors: " .. RFXCountMS) 880 luup.log(" keyfob sensors: " .. RFXCountKF) 881 luup.log(" light switches: " .. RFXCountLS) 882 luup.log(" window coverings: " .. RFXCOM_HAR_Count) 883 884 -- Synch the new tree with the old three 885 luup.log("Start sync") 886 luup.chdev.sync(THIS_DEVICE, child_devices) 887 luup.log("End sync") 888 -- Remember the newly added device 889 device = findChild(THIS_DEVICE, lsID ) 890 end 891 892 893 -- If we have found the device with the correct ID, then we have to act on the 894 -- command received 895 if device ~= nil then 896 luup.log("Device found or created, now processing command " .. lsCmd .. " for " .. lsID) 897 898 -- Execution door sensors same as motion sensors 899 if lsSensorType == RFXConstants.sensorTypeDoor or lsSensorType == RFXConstants.sensorTypeMotion then 900 local TrippedValue = "0" 901 if lsCmd == RFXConstants.cmdAlert then TrippedValue = "1" end 902 luup.log( "Set tripped value " .. TrippedValue .. " to device " .. lsID ) 903 luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", TrippedValue, device) 904 end 905 906 -- Execution for keyfobs 907 -- Arm or Disarm all door and motion sensors when keyfob armed or disarmed 908 -- Set trip state keyfox as indication home or away 909 if lsSensorType == RFXConstants.sensorTypeKeyFob then 910 luup.log("KeyFob action: " .. lsCmd) 911 912 if lsCmd == RFXConstants.cmdArmAway or lsCmd == RFXConstants.cmdArmHome or lsCmd == RFXConstants.cmdDisarm then 913 ArmDisarmAll(lsCmd) 914 elseif lsCmd == RFXConstants.cmdPanic then 915 -- not implemented 916 elseif lsCmd == RFXConstants.cmdGroupOn then 917 -- not implemented 918 end 919 end 920 921 -- Execution light switches. 922 -- Set Status based on cmdOn or cmdOff 923 if lsSensorType == RFXConstants.sensorTypeControler then 924 local newTargetValue = "0" 925 926 if lsCmd == RFXConstants.cmdOn then newTargetValue = "1" end 927 928 luup.log("SET TARGET from " .. lsID .. " with value " .. newTargetValue) 929 luup.variable_set("urn:upnp-org:serviceId:SwitchPower1","Status",newTargetValue,device) 930 end 931 932 end 933 934 end 935 936 ------------------------------------------------------------------------ 937 -- Arm or Disarm 938 -- 939 -- Arm or Disarm all motion and door sensors based on command given. 940 -- KeyFob sensor gets armed or disarmed also and trip state 941 -- is used to indicate home or away status (triped = home) 942 ------------------------------------------------------------------------ 943 944 function ArmDisarmAll(lsCmd) 945 local newArmedValue = "1" -- armed 946 local newTrippedValue = "1" -- home 947 948 if lsCmd == RFXConstants.cmdDisarm then 949 newArmedValue = "0" 950 newTrippedValue = "0" 951 end 952 if lsCmd == RFXConstants.cmdArmAway then newTrippedValue = "0" end 953 luup.log("urn:ActiveRFID:serviceId:RFIDTransmitter1 Action::SetArmed:" .. newArmedValue) 954 955 -- Iterate all door sensors and set armed value 956 for teller = 1, RFXCountDS do 957 local lsOtherDevices = findChild(THIS_DEVICE, RFXDevicesDS[teller] ) 958 959 luup.log("Action::SetArmed: " .. newArmedValue .. " for door sensor device " .. RFXDevicesDS[teller] .. "/" .. lsOtherDevices) 960 luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1","Armed",newArmedValue,lsOtherDevices) 961 end 962 963 -- Iterate all motion sensors and set armed value 964 for teller = 1, RFXCountMS do 965 local lsOtherDevices = findChild(THIS_DEVICE, RFXDevicesMS[teller] ) 966 967 luup.log("Action::SetArmed: " .. newArmedValue .. " for motion sensor device " .. RFXDevicesMS[teller] .. "/" .. lsOtherDevices) 968 luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1","Armed",newArmedValue,lsOtherDevices) 969 970 end 971 972 -- Iterate all keyfobs and set armed value and 973 -- set tripped value based on armed-home (1) or armed-away (0) 974 for teller = 1, RFXCountKF do 975 local lsOtherDevices = findChild(THIS_DEVICE, RFXDevicesKF[teller] ) 976 977 luup.log("Action::SetArmed: " .. newArmedValue .. "for KeyFob device " .. RFXDevicesKF[teller] .. "/" .. lsOtherDevices) 978 luup.log("Action::SetTripped: " .. newTrippedValue .. "for KeyFob device " .. RFXDevicesKF[teller] .. "/" .. lsOtherDevices) 979 980 luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1","Armed",newArmedValue,lsOtherDevices) 981 luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",newTrippedValue,lsOtherDevices) 982 end 983 end 984 985 986 -- Thanks to guessed for this snippet. 987 function findChild(parentDevice, label) 988 for k, v in pairs(luup.devices) do 989 if (v.device_num_parent == parentDevice and v.id == label) then 990 return k 991 end 992 end 993 994 -- Dump a copy of the Global Module list for debugging purposes. 995 luup.log("findChild cannot find parentDevice: " .. tostring(parentDevice) .. " label: " .. label) 996 --for k, v in pairs(luup.devices) do 997 -- luup.log("Device Number: " .. k .. 998 -- " v.device_type: " .. tostring(v.device_type) .. 999 -- " v.device_num_parent: " .. tostring(v.device_num_parent) .. 1000 -- " v.id: " .. tostring(v.id) 1001 -- ) 1002 --end 1003 end 332 1004 333 -- Thanks to guessed for this snippet.334 function findChild(parentDevice, label)335 for k, v in pairs(luup.devices) do336 if (v.device_num_parent == parentDevice and v.id == label) then337 return k338 end339 end340 341 -- Dump a copy of the Global Module list for debugging purposes.342 luup.log("findChild cannot find parentDevice: " .. tostring(parentDevice) .. " label: " .. label)343 for k, v in pairs(luup.devices) do344 luup.log("Device Number: " .. k ..345 " v.device_type: " .. tostring(v.device_type) ..346 " v.device_num_parent: " .. tostring(v.device_num_parent) ..347 " v.id: " .. tostring(v.id)348 )349 end350 end351 352 1005 </functions> 353 1006 354 1007 <incoming> 355 1008 <lua> 356 357 358 359 360 -- If this is the first byte then create a call back timer to process the data361 362 363 364 365 366 367 1009 -- When still starting up ignore any data... 1010 if ( startupReady == 1 ) then 1011 local tempdata = tostring(lul_data) 1012 1013 -- if this is the first byte then create a call back timer to process the data 1014 local liStartCallback = 0 1015 if ( #buffer == 0 ) then 1016 liStartCallback = 1 1017 end 1018 1019 -- and store data in buffer. 1020 buffer = buffer .. tempdata 368 1021 369 1022 -- do callback 370 1023 if ( liStartCallback == 1 ) then 371 372 end 373 374 1024 luup.call_delay("endOfData", 1 , "test delay success") 1025 end 1026 end 1027 </lua> 375 1028 </incoming> 376 1029 377 1030 <startup>mainStartup</startup> 378 <actionList> 379 <action> 380 <serviceId>urn:upnp-esweb-nl:serviceId:rfxcom1</serviceId> 381 <name>AddHarrisonCurtain</name> 382 <run> 383 384 local lsHouseCode = lul_settings.HouseCode 385 luup.log("Add harrison curtain with id: " .. lsHouseCode) 386 387 local HAR_DEV = findChild(THIS_DEVICE, lsHouseCode ) 388 389 if HAR_DEV == nil then 390 luup.log( "harrison device not found... will create" ) 391 392 local child_devices = luup.chdev.start(THIS_DEVICE); 393 394 for teller = 1, RFXCOM_HAR_Count do 395 luup.chdev.append(THIS_DEVICE, child_devices, RFXCOM_HAR_Devices[teller], 396 "Harrison #" .. RFXCOM_HAR_Devices[teller] , "urn:schemas-micasaverde-com:device:WindowCovering:1", 397 "D_RFXCOMHarrison.xml","","",false) 398 end 399 400 luup.chdev.append(THIS_DEVICE, child_devices, lsHouseCode, 401 "Harrison #" .. lsHouseCode , "urn:schemas-micasaverde-com:device:WindowCovering:1", 402 "D_RFXCOMHarrison.xml","","",false) 403 404 RFXCOM_HAR_Count = RFXCOM_HAR_Count + 1 405 RFXCOM_HAR_Devices[RFXCOM_HAR_Count] = lsHouseCode 406 407 luup.chdev.sync(THIS_DEVICE, child_devices) 408 409 HAR_DEV = findChild(THIS_DEVICE, lsHouseCode ) 410 411 else 412 luup.log( "harrison device found... nothing to create.." ) 413 414 end 415 </run> 416 </action> 417 <action> 418 <serviceId>urn:upnp-org:serviceId:WindowCovering1</serviceId> 419 <name>Stop</name> 420 <run> 421 local har_id = luup.devices[lul_device].id 422 SendHarrisonCmd( har_id, "STOP") 423 </run> 424 </action> 425 <action> 426 <serviceId>urn:upnp-org:serviceId:WindowCovering1</serviceId> 427 <name>Up</name> 428 <run> 429 luup.variable_set("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",0,lul_device) 430 local har_id = luup.devices[lul_device].id 431 SendHarrisonCmd( har_id, "OPEN") 432 </run> 433 </action> 434 <action> 435 <serviceId>urn:upnp-org:serviceId:WindowCovering1</serviceId> 436 <name>Down</name> 437 <run> 438 luup.variable_set("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",1,lul_device) 439 local har_id = luup.devices[lul_device].id 440 SendHarrisonCmd( har_id, "CLOSE") 441 </run> 442 </action> 443 444 <action> 445 <serviceId>urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1</serviceId> 446 <name>SetStatus</name> 447 <run> 448 luup.variable_set("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",lul_settings.newStatusValue,lul_device) 449 local har_id = luup.devices[lul_device].id 450 if ( lul_settings.newStatusValue == "1" ) then 451 SendHarrisonCmd( har_id, "OPEN") 452 else 453 SendHarrisonCmd( har_id, "CLOSE") 454 end 455 </run> 456 </action> 457 <action> 458 <serviceId>urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1</serviceId> 459 <name>GetStatus</name> 460 <run> 461 lul_settings.ResultStatus = luup.variable_get("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",lul_device) 462 </run> 463 </action> 464 </actionList> 465 1031 <actionList> 1032 <action> 1033 <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId> 1034 <name>SetTarget</name> 1035 <run> 1036 local ls_id = luup.devices[lul_device].id 1037 local lul_reverse = luup.variable_get("urn:micasaverde-com:serviceId:HaDevice1","ReverseOnOff",lul_device) 1038 1039 luup.log("SET TARGET from " .. ls_id .. " with value " .. lul_settings.newTargetValue) 1040 1041 if ( lul_settings.newTargetValue == "1" or (lul_settings.newTargetValue=="0" and lul_reverse=="1") ) then 1042 SendCmd( ls_id,RFXConstants.cmdOn ) 1043 else 1044 SendCmd( ls_id,RFXConstants.cmdOff ) 1045 end 1046 luup.variable_set("urn:upnp-org:serviceId:SwitchPower1","Status",lul_settings.newTargetValue,lul_device) 1047 </run> 1048 </action> 1049 1050 <action> 1051 <serviceId>urn:micasaverde-com:serviceId:SecuritySensor1</serviceId> 1052 <name>SetArmed</name> 1053 <run> 1054 --debug("Action::SetArmed:"..lul_settings.newArmedValue) 1055 luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1", "Armed", lul_settings.newArmedValue, lul_device) 1056 </run> 1057 </action> 1058 1059 <action> 1060 <serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId> 1061 <name>ToggleState</name> 1062 <run> 1063 --debug("Action::ToggleState:" .. lul_device) 1064 </run> 1065 </action> 1066 1067 1068 <action> 1069 <serviceId>urn:upnp-esweb-nl:serviceId:rfxcom1</serviceId> 1070 <name>AddHarrisonCurtain</name> 1071 <run> 1072 local lsHouseCode = lul_settings.HouseCode 1073 actOnMessage(RFXConstants.sensorTypeWindowCovering,lsHouseCode,"") 1074 </run> 1075 </action> 1076 <action> 1077 <serviceId>urn:upnp-org:serviceId:WindowCovering1</serviceId> 1078 <name>Stop</name> 1079 <run> 1080 local har_id = luup.devices[lul_device].id 1081 SendHarrisonCmd( har_id, "STOP") 1082 </run> 1083 </action> 1084 <action> 1085 <serviceId>urn:upnp-org:serviceId:WindowCovering1</serviceId> 1086 <name>Up</name> 1087 <run> 1088 luup.variable_set("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",0,lul_device) 1089 local har_id = luup.devices[lul_device].id 1090 SendHarrisonCmd( har_id, "OPEN") 1091 </run> 1092 </action> 1093 <action> 1094 <serviceId>urn:upnp-org:serviceId:WindowCovering1</serviceId> 1095 <name>Down</name> 1096 <run> 1097 luup.variable_set("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",1,lul_device) 1098 local har_id = luup.devices[lul_device].id 1099 SendHarrisonCmd( har_id, "CLOSE") 1100 </run> 1101 </action> 1102 1103 <action> 1104 <serviceId>urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1</serviceId> 1105 <name>SetStatus</name> 1106 <run> 1107 luup.variable_set("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",lul_settings.newStatusValue,lul_device) 1108 local har_id = luup.devices[lul_device].id 1109 if ( lul_settings.newStatusValue == "1" ) then 1110 SendHarrisonCmd( har_id, "OPEN") 1111 else 1112 SendHarrisonCmd( har_id, "CLOSE") 1113 end 1114 </run> 1115 </action> 1116 <action> 1117 <serviceId>urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1</serviceId> 1118 <name>GetStatus</name> 1119 <run> 1120 lul_settings.ResultStatus = luup.variable_get("urn:upnp-esweb-nl:serviceId:RFXCOMHarrison1","CurtainStatus",lul_device) 1121 </run> 1122 </action> 1123 </actionList> 466 1124 </implementation> -
/S_RFXCOM.xml
r1 r3 12 12 <shortCode>msg</shortCode> 13 13 </stateVariable> 14 <stateVariable allowRepeats="no"> 15 <name>Autocreate</name> 16 <sendEventsAttribute>no</sendEventsAttribute> 17 <dataType>string</dataType> 18 </stateVariable> 14 19 </serviceStateTable> 15 20 <actionList> … … 42 47 </argument> 43 48 </argumentList> 44 </action> 49 </action> 45 50 </actionList> 46 51 </scpd>
Note: See TracChangeset
for help on using the changeset viewer.