The files contained in this repository can be downloaded to your computer using a svn client.
On Linux you simply type the command displayed below.
This URL has Read-Only access.
root / trunk / DomotiGaServer / CCUL.class @ 649
History | View | Annotate | Download (21.2 kB)
| 1 | ' Gambas class file |
|---|---|
| 2 | |
| 3 | ' Description: |
| 4 | ' CCUL.class |
| 5 | ' Connect to CULFW interface via tcp socket or serial port. |
| 6 | |
| 7 | ' Development Status: |
| 8 | ' Just started. |
| 9 | |
| 10 | ' DomotiGa - an open source home automation program. |
| 11 | ' Copyright(C) 2008-2011 Ron Klinkien |
| 12 | |
| 13 | ' Read file called COPYING for license details. |
| 14 | |
| 15 | PROPERTY TCPHost AS String |
| 16 | PROPERTY TCPPort AS Integer |
| 17 | PROPERTY Interface AS String |
| 18 | PROPERTY SerPort AS String |
| 19 | PROPERTY Baud AS String |
| 20 | PROPERTY CULDebug AS Boolean |
| 21 | PROPERTY Model AS Integer |
| 22 | |
| 23 | PRIVATE sTCPHost AS String |
| 24 | PRIVATE iTCPPort AS Integer |
| 25 | PRIVATE sInterface AS String |
| 26 | PRIVATE sSerPort AS String |
| 27 | PRIVATE sBaud AS String |
| 28 | PRIVATE bCULDebug AS Boolean |
| 29 | PRIVATE iModel AS Integer |
| 30 | |
| 31 | PUBLIC hCUL AS NEW Socket |
| 32 | PUBLIC hCULSer AS NEW SerialPort |
| 33 | PUBLIC bSimulate AS Boolean = FALSE |
| 34 | |
| 35 | PRIVATE bFirstByte AS Boolean = TRUE |
| 36 | PRIVATE RecBuf AS Byte[255] |
| 37 | PRIVATE bMessage AS Boolean = FALSE |
| 38 | PRIVATE iByteCount AS Integer = 0 |
| 39 | |
| 40 | ' FS20 |
| 41 | PRIVATE sFS20Values AS String[] = ["Off", "Dim 6", "Dim 12", "Dim 18", "Dim 25", "Dim 31", "Dim 37", "Dim 43", "Dim 50", "Dim 56", "Dim 62", "Dim 68", "Dim 75", "Dim 81", "Dim 87", "Dim 93", "Dim 100", "On", "Toggle", "DimUp", "DimDown", "DimUpDown", "Timer", "SendState", "Off-For-Timer", "On-For-Timer", "On-Old-For-Timer", "Reset", "Ramp-On-Time", "Ramp-Of-Time", "On-Old-For-Timer-Prev", "On-100-For-Timer-Prev"] |
| 42 | |
| 43 | ' FHT |
| 44 | CONST FHT_SYNCTIME AS Byte = &H2C |
| 45 | CONST FHT_MODE AS Byte = &H3D |
| 46 | CONST FHT_DESIREDTEMP AS Byte = &H41 |
| 47 | CONST FHT_STATUS AS Byte = &H44 |
| 48 | CONST FHT_DAYTEMP AS Byte = &H82 |
| 49 | CONST FHT_NIGHTTEMP AS Byte = &H84 |
| 50 | CONST FHT_WINDOWOPENTEMP AS Byte = &H8A |
| 51 | |
| 52 | PUBLIC SUB CUL_Ready() |
| 53 | |
| 54 | Main.WriteLog(("CUL TCP socket connected."))
|
| 55 | Init() |
| 56 | |
| 57 | END |
| 58 | |
| 59 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 60 | ' connect to the host:port |
| 61 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 62 | PUBLIC FUNCTION ConnectTCP() AS Boolean |
| 63 | |
| 64 | ' try to close the connection |
| 65 | TRY hCUL.Close |
| 66 | |
| 67 | ' get a new one |
| 68 | hCUL = NEW Socket AS "CUL" |
| 69 | hCUL.Connect(sTCPHost, iTCPPort) |
| 70 | |
| 71 | ' all ok |
| 72 | RETURN TRUE |
| 73 | |
| 74 | CATCH ' some errors |
| 75 | Main.WriteLog(("CUL Error: ") & ERROR.Text)
|
| 76 | RETURN FALSE |
| 77 | |
| 78 | END |
| 79 | |
| 80 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 81 | ' connect to the serial port |
| 82 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 83 | PUBLIC FUNCTION ConnectSerial() AS Boolean |
| 84 | |
| 85 | ' try to close the connection |
| 86 | TRY hCULSer.Close |
| 87 | |
| 88 | ' get a new one |
| 89 | hCULSer = NEW Serialport AS "CULSer" |
| 90 | WITH hCULSer |
| 91 | .PortName = sSerPort |
| 92 | .Speed = sBaud |
| 93 | .Parity = 0 |
| 94 | .DataBits = 8 |
| 95 | .StopBits = 1 |
| 96 | .FlowControl = 0 |
| 97 | .Open() |
| 98 | END WITH |
| 99 | |
| 100 | Init() |
| 101 | |
| 102 | ' all ok |
| 103 | RETURN TRUE |
| 104 | |
| 105 | CATCH ' some errors |
| 106 | Main.WriteLog(("CUL Error: ") & ERROR.Text)
|
| 107 | RETURN FALSE |
| 108 | |
| 109 | END |
| 110 | |
| 111 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 112 | ' disconnect from the host |
| 113 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 114 | PUBLIC FUNCTION Disconnect() AS Boolean |
| 115 | |
| 116 | ' try to close the connection |
| 117 | TRY hCUL.Close |
| 118 | TRY hCULSer.Close |
| 119 | IF InStr(sInterface, "tcp") THEN |
| 120 | Main.WriteLog(("CUL TCP socket close."))
|
| 121 | ELSE |
| 122 | Main.WriteLog(("CUL serial port close."))
|
| 123 | END IF |
| 124 | ' all ok |
| 125 | RETURN TRUE |
| 126 | |
| 127 | CATCH ' some errors |
| 128 | Main.WriteLog(("CUL Error: ") & ERROR.Text)
|
| 129 | RETURN FALSE |
| 130 | |
| 131 | END |
| 132 | |
| 133 | PUBLIC SUB CUL_Error() |
| 134 | |
| 135 | DIM sString AS String = "CUL: " |
| 136 | |
| 137 | ' handle error |
| 138 | SELECT CASE hCUL.Status |
| 139 | CASE Net.CannotCreateSocket |
| 140 | Main.WriteLog(sString & ("The system does not allow to create a socket."))
|
| 141 | CASE Net.HostNotFound |
| 142 | Main.WriteLog(sString & ("Host '") & sTCPHost & ("' not found."))
|
| 143 | CASE Net.ConnectionRefused |
| 144 | Main.WriteLog(sString & ("Unable to connect. Connection refused."))
|
| 145 | CASE Net.CannotRead |
| 146 | Main.WriteLog(sString & ("Error reading data."))
|
| 147 | CASE Net.CannotWrite |
| 148 | Main.WriteLog(sString & ("Error writing data."))
|
| 149 | END SELECT |
| 150 | |
| 151 | END |
| 152 | |
| 153 | PUBLIC SUB CUL_Read() |
| 154 | |
| 155 | DIM bData AS Byte |
| 156 | |
| 157 | TRY READ #hCUL, bData |
| 158 | IF ERROR THEN Main.WriteDebugLog(("[CUL] Error reading data from the TCP port! -> ") & Error.Text)
|
| 159 | ProcessReceivedChar(bData) |
| 160 | |
| 161 | END |
| 162 | |
| 163 | PUBLIC SUB CULSer_Read() |
| 164 | |
| 165 | DIM bData AS Byte |
| 166 | |
| 167 | TRY READ #hCULSer, bData |
| 168 | IF ERROR THEN Main.WriteDebugLog(("[CUL] Error reading data from the serial port! -> ") & Error.Text)
|
| 169 | ProcessReceivedChar(bData) |
| 170 | |
| 171 | END |
| 172 | |
| 173 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 174 | ' initialize interface |
| 175 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 176 | PUBLIC FUNCTION Init() |
| 177 | |
| 178 | SendCommand("X21\r\n")
|
| 179 | IF bCULDebug THEN Main.WriteRFXDebugLog("[CUL] > X21\n")
|
| 180 | GetVersion() |
| 181 | |
| 182 | ParseDump() |
| 183 | |
| 184 | END |
| 185 | |
| 186 | ' just here for development/debugging |
| 187 | PUBLIC SUB ParseDump() |
| 188 | |
| 189 | DIM hFile AS File |
| 190 | DIM sLine AS String |
| 191 | |
| 192 | TRY hFile = OPEN "/home/ron/FHT.txt" FOR INPUT |
| 193 | IF ERROR THEN RETURN |
| 194 | |
| 195 | WHILE NOT Eof(hFile) |
| 196 | LINE INPUT #hFile, sLine |
| 197 | IF Len(sLine) > 5 THEN Simulate(sLine) |
| 198 | WEND |
| 199 | |
| 200 | END |
| 201 | |
| 202 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 203 | ' initialize interface |
| 204 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 205 | PUBLIC FUNCTION GetVersion() |
| 206 | |
| 207 | SendCommand("V\r\n")
|
| 208 | IF bCULDebug THEN Main.WriteRFXDebugLog("[CUL] > V\n")
|
| 209 | |
| 210 | END |
| 211 | |
| 212 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 213 | ' inject packet into parser. |
| 214 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 215 | PUBLIC SUB Simulate(sPacket AS String) |
| 216 | |
| 217 | DIM iCnt AS Integer |
| 218 | |
| 219 | bFirstByte = TRUE |
| 220 | IF bCULDebug THEN Main.WriteRFXDebugLog(("[CUL] CUL receiver Simulate String: ") & sPacket & "\n")
|
| 221 | |
| 222 | FOR iCnt = 1 TO Len(sPacket) |
| 223 | ProcessReceivedChar(Asc(Mid(sPacket, iCnt, 1))) |
| 224 | NEXT |
| 225 | ProcessReceivedChar(&HD) |
| 226 | ProcessReceivedChar(&HA) |
| 227 | bSimulate = FALSE |
| 228 | |
| 229 | END SUB |
| 230 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 231 | ' send a command to the interface |
| 232 | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 233 | PUBLIC FUNCTION SendCommand(sBuffer AS String) |
| 234 | |
| 235 | IF sInterface = "tcp" THEN |
| 236 | ' send the message to the tcp stream |
| 237 | TRY WRITE #hCUL, sBuffer, Len(sBuffer) |
| 238 | IF ERROR THEN Main.WriteRFXDebugLog(("[CUL] Unable to write to TCP port! -> ") & Error.Text)
|
| 239 | ELSE |
| 240 | ' send the message to the serial port |
| 241 | TRY WRITE #hCULSer, sBuffer, Len(sBuffer) |
| 242 | IF ERROR THEN Main.WriteRFXDebugLog(("[CUL] Unable to write to serial port! -> ") & Error.Text)
|
| 243 | ENDIF |
| 244 | |
| 245 | END |
| 246 | |
| 247 | PRIVATE SUB ProcessReceivedChar(bTemp AS Byte) |
| 248 | |
| 249 | IF bFirstByte = TRUE THEN |
| 250 | bFirstByte = FALSE |
| 251 | iByteCount = 0 |
| 252 | IF bCULDebug THEN Main.WriteRFXDebugLog("[CUL] < ", 0)
|
| 253 | ENDIF |
| 254 | |
| 255 | Main.ControlLed("CUL", "On")
|
| 256 | |
| 257 | RecBuf[iByteCount] = bTemp |
| 258 | IF bTemp = &HA THEN |
| 259 | iByteCount -= 2 ' do not count \r\n |
| 260 | bMessage = TRUE |
| 261 | ELSE |
| 262 | IF bCULDebug AND IF (bTemp <> &HD) THEN Main.WriteRFXDebugLog(Chr(bTemp), 1) |
| 263 | INC iByteCount |
| 264 | ENDIF |
| 265 | |
| 266 | IF bMessage THEN Display_Message() |
| 267 | |
| 268 | END |
| 269 | |
| 270 | PRIVATE SUB Display_Message() |
| 271 | |
| 272 | DIM iDeviceId, iCnt, iCmd, iDur, iI, iJ, iRSSI AS Integer |
| 273 | DIM sHouseCode, sAddress, sValue, sValue2, sCmd, sEMType, sEMCumulValue, sEMPeakValue, sMsgCounter, sBatt, sVal, sId, sSval, sFv AS String |
| 274 | DIM sWarn, sLowTemp, sSensor, sWindow, sOffset AS String |
| 275 | DIM aEMType AS String[] = ["", "EM1000-S", "EM1000-EM", "EM1000-GZ"] |
| 276 | DIM aFHTc2m AS String[] = ["auto", "manual", "holiday", "holiday-short"] |
| 277 | DIM bConfirm AS Boolean |
| 278 | |
| 279 | bMessage = FALSE |
| 280 | bFirstByte = TRUE |
| 281 | |
| 282 | IF bCULDebug THEN Main.WriteRFXDebugLog("\n", 1)
|
| 283 | |
| 284 | SELECT CASE Chr(RecBuf[0]) |
| 285 | CASE "F" ' FS20 message |
| 286 | ' F <Hex> |
| 287 | ' <Hex> is a hex string with the following format: |
| 288 | ' hhhhaacc or hhhhaaccee, where |
| 289 | ' hhhh is the FS20 housecode |
| 290 | ' aa is the FS20 device address |
| 291 | ' cc is the FS20 command |
| 292 | ' ee is the FS20 timespec. Note that cc must have the extension bit set. |
| 293 | ' Example: F12340111 |
| 294 | |
| 295 | ' check for valid packet size |
| 296 | IF iByteCount < 9 OR IF iByteCount > 12 THEN |
| 297 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] FS20 message received with invalid length of " & iByteCount & " bytes!"))
|
| 298 | RETURN |
| 299 | ENDIF |
| 300 | |
| 301 | sHouseCode = Chr(RecBuf[1]) & Chr(RecBuf[2]) & Chr(RecBuf[3]) & Chr(RecBuf[4]) |
| 302 | sAddress = Chr(RecBuf[5]) & Chr(RecBuf[6]) |
| 303 | iCmd = Val("&H" & Chr(RecBuf[7]) & Chr(RecBuf[8]))
|
| 304 | |
| 305 | ' signal |
| 306 | IF iByteCount > 11 THEN |
| 307 | iRSSI = Val("&H" & Chr(RecBuf[11]) & Chr(RecBuf[12]))
|
| 308 | ELSE |
| 309 | iRSSI = Val("&H" & Chr(RecBuf[9]) & Chr(RecBuf[10]))
|
| 310 | ENDIF |
| 311 | |
| 312 | ' calculate duration if extension bit is set |
| 313 | IF (iCmd AND &H20) THEN |
| 314 | iDur = Val("&H" & Chr(RecBuf[9]) & Chr(RecBuf[10]))
|
| 315 | iI = (iDur AND &HF0) / 16 |
| 316 | iJ = (iDur AND &HF) |
| 317 | iDur = (iI ^ 2) * iJ * 0.25 |
| 318 | |
| 319 | ' calculate cmd |
| 320 | iCmd = iCmd XOR &H20 |
| 321 | ENDIF |
| 322 | |
| 323 | ' test if cmd value is known |
| 324 | TRY sValue = sFS20Values[iCmd] |
| 325 | IF NOT ERROR THEN |
| 326 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] FS20 message received with address '") & sHouseCode & sAddress & "' (" & Hex2Four(sHouseCode & sAddress) & ") and command '" & sValue & "'" & IIf(iDur, " duration: " & iDur, "") & IIf(iRSSI, " rssi: " & iRSSI, ""))
|
| 327 | ' find device id |
| 328 | iDeviceId = Devices.Find(sHouseCode & sAddress, Devices.FindInterface("CUL Interface"), "FS20")
|
| 329 | IF iCmd < 17 THEN |
| 330 | ' update value1 |
| 331 | IF iDeviceId THEN Devices.ValueUpdate(iDeviceId, sValue, "", "", "") |
| 332 | ELSE |
| 333 | ' update value2 |
| 334 | IF iDeviceId THEN Devices.ValueUpdate(iDeviceId, "", sValue, "", "") |
| 335 | ENDIF |
| 336 | ELSE |
| 337 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] FS20 message received with address '") & sHouseCode & sAddress & "' (" & Hex2Four(sHouseCode & sAddress) & ") and unknown/invalid command '" & Hex(iCmd) & "'")
|
| 338 | ENDIF |
| 339 | CASE "T" ' FHT messages |
| 340 | ' check for valid packet size |
| 341 | IF iByteCount < 9 OR IF iByteCount > 13 THEN |
| 342 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] FHT message received with invalid length of " & iByteCount & " bytes!"))
|
| 343 | RETURN |
| 344 | ENDIF |
| 345 | |
| 346 | sAddress = Chr(RecBuf[1]) & Chr(RecBuf[2]) & Chr(RecBuf[3]) & Chr(RecBuf[4]) & Chr(RecBuf[5]) & Chr(RecBuf[6]) |
| 347 | iCmd = Val("&H" & Chr(RecBuf[7]) & Chr(RecBuf[8]))
|
| 348 | |
| 349 | IF iByteCount = 10 THEN ' must be FHT FTK sensor |
| 350 | ' T <Hex> |
| 351 | ' <Hex> is a hex string with the following format: |
| 352 | ' ccccccxx |
| 353 | ' where cccccc being the id of the sensor in hex |
| 354 | ' xx being the current status like 'open,close,sync,test,battlow' |
| 355 | SELECT CASE iCmd |
| 356 | CASE &H02, &H82 |
| 357 | sValue = "Closed" |
| 358 | sBatt = "Ok" |
| 359 | CASE &H01, &H81 |
| 360 | sValue = "Open" |
| 361 | sBatt = "Ok" |
| 362 | CASE &H11, &H91 |
| 363 | sValue = "Open" |
| 364 | sBatt = "Low" |
| 365 | CASE &H12, &H92 |
| 366 | sValue = "Closed" |
| 367 | sBatt = "Low" |
| 368 | CASE &H0C |
| 369 | sValue2 = "Sync:Syncing" |
| 370 | CASE &H0F |
| 371 | sValue2 = "Test:Success" |
| 372 | END SELECT |
| 373 | |
| 374 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] FHT TFK message received with address '") & sHouseCode & sAddress & "', status '" & IIf(Len(sValue2), sValue2, sValue) & "' and battery level '" & sBatt & "'")
|
| 375 | ' find device id |
| 376 | iDeviceId = Devices.Find(sHouseCode & sAddress, Devices.FindInterface("CUL Interface"), "FHTTFK")
|
| 377 | IF iDeviceId THEN |
| 378 | ' update values |
| 379 | Devices.ValueUpdate(iDeviceId, sValue, sValue2, "", "") |
| 380 | ' store battery status |
| 381 | IF (Len(sBatt) > 1) THEN Devices.Battery(iDeviceId, sBatt) |
| 382 | ENDIF |
| 383 | ELSE ' FHT80 message |
| 384 | ' T15157D671216 |
| 385 | ' T15177E7712FA |
| 386 | ' T5A334369001A |
| 387 | ' T <Hex> |
| 388 | ' <Hex> is a hex string with the following format: |
| 389 | ' Thhhhccnnvvxx |
| 390 | ' hhhh = address |
| 391 | ' cc = command |
| 392 | ' nn = report value / id |
| 393 | ' vv = value |
| 394 | ' xx = rssi |
| 395 | sAddress = Chr(RecBuf[1]) & Chr(RecBuf[2]) & Chr(RecBuf[3]) & Chr(RecBuf[4]) |
| 396 | iCmd = Val("&H" & Chr(RecBuf[5]) & Chr(RecBuf[6]))
|
| 397 | sCmd = FHTCode(iCmd) |
| 398 | |
| 399 | IF iByteCount > 9 THEN |
| 400 | sVal = Val("&H" & (Chr(RecBuf[9]) & Chr(RecBuf[10])))
|
| 401 | ELSE IF iByteCount < 9 THEN |
| 402 | sCmd = "FHT short message" |
| 403 | sVal = "" |
| 404 | ENDIF |
| 405 | |
| 406 | IF iByteCount > 11 THEN |
| 407 | ' rssi |
| 408 | iRSSI = Val("&H" & Chr(RecBuf[11]) & Chr(RecBuf[12]))
|
| 409 | ENDIF |
| 410 | |
| 411 | ' IF NOT Len(sVal) OR IF sCmd = "report1" OR IF sCmd = "report2" THEN |
| 412 | IF sCmd = "report1" OR IF sCmd = "report2" THEN |
| 413 | sVal = Val("&H" & (Chr(RecBuf[7]) & Chr(RecBuf[8])))
|
| 414 | bConfirm = TRUE |
| 415 | ENDIF |
| 416 | |
| 417 | IF InStr(sCmd, "-from") OR IF InStr(sCmd, "-to") THEN ' time format |
| 418 | sVal = Format(Val(sVal) / 6, "0#") & ":" & Format((Val(sVal) MOD 6) * 10, "0#") |
| 419 | ELSE IF sCmd = "mode" ' auto, manual, holiday, holiday-short |
| 420 | sVal = aFHTc2m[sVal] |
| 421 | ELSE IF InStr(sCmd, "-temp") |
| 422 | sVal = sVal / 2 |
| 423 | sVal = Format(sVal, "#.0") |
| 424 | ELSE IF sCmd = "lowtemp-offset" |
| 425 | sVal = Format(sVal, "#.0") |
| 426 | ELSE IF InStr(sCmd, "actuator") |
| 427 | sSval = Chr(RecBuf[9]) & Chr(RecBuf[10]) |
| 428 | sFv = (100 * Val(sVal) / 255 + 0.5) & "%" |
| 429 | sId = Chr(RecBuf[8]) |
| 430 | IF sSval = "A0" OR IF sSval = "B0" THEN |
| 431 | sVal = sFv ' sync in the summer |
| 432 | ELSE IF Right(sSval, 1) = "0" THEN |
| 433 | sVal = "syncnow" |
| 434 | ELSE IF Right(sSval, 1) = "1" THEN |
| 435 | sVal = "99%" ' FHT set to 30.5, FHT80B="ON" |
| 436 | ELSE IF Right(sSval, 1) = "2" THEN |
| 437 | sVal = "0%" ' FHT set to 5.5 |
| 438 | ELSE IF Right(sSval, 1) = "6" THEN |
| 439 | sVal = sFv |
| 440 | ELSE IF Right(sSval, 1) = "8" THEN |
| 441 | sVal = "offset: " & sFv |
| 442 | ELSE IF sSval = "2A" OR IF sSval = "3A" THEN |
| 443 | sVal = "lime-protection" |
| 444 | ELSE IF sSval = "AA" OR IF sSval = "BA" THEN |
| 445 | sVal = sFv ' lime protection bug |
| 446 | ELSE IF Right(sSval, 1) = "C" THEN |
| 447 | sVal = "synctime: " & (Val(sVal) / 2) - 1 |
| 448 | ELSE IF Right(sSval, 1) = "E" THEN |
| 449 | sVal = "test" |
| 450 | ELSE IF Right(sSval, 1) = "F" THEN |
| 451 | sVal = "pair" |
| 452 | ELSE |
| 453 | sVal = "unknown" |
| 454 | ENDIF |
| 455 | |
| 456 | IF InStr(sVal, "%") AND IF sId = 0 THEN |
| 457 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] Position " & sId & " " & sVal))
|
| 458 | ENDIF |
| 459 | ELSE IF sCmd = "measured-low" |
| 460 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] Measured Low " & sVal))
|
| 461 | ' GOTO fhtlog; |
| 462 | |
| 463 | ELSE IF sCmd = "measured-high" |
| 464 | sOffset = 0 |
| 465 | sVal = sVal * 256 |
| 466 | sVal = sVal / 10 |
| 467 | sVal = Format(sVal, "#.0") |
| 468 | 'sCmd = "measured-temp" |
| 469 | ELSE IF sCmd = "warnings" |
| 470 | IF (sVal AND 1) THEN |
| 471 | sWarn = "Battery low" |
| 472 | sBatt = "Low" |
| 473 | ENDIF |
| 474 | IF (sVal AND 2) THEN |
| 475 | IF sWarn THEN sWarn &= "; " |
| 476 | sWarn &= "Temp too low" |
| 477 | sLowTemp = "Warn" |
| 478 | ENDIF |
| 479 | IF (sVal AND 32) THEN |
| 480 | IF sWarn THEN sWarn &= "; " |
| 481 | sWarn &= "Window open" |
| 482 | sWindow = "Open" |
| 483 | ENDIF |
| 484 | IF (sVal AND 16) THEN |
| 485 | IF sWarn THEN sWarn &= "; " |
| 486 | sWarn &= "Window sensor fault" |
| 487 | sSensor = "Fault" |
| 488 | ENDIF |
| 489 | ' default value if not set |
| 490 | IF NOT Len(sBatt) THEN sBatt = "Ok" |
| 491 | IF NOT Len(sLowTemp) THEN sLowTemp = "Ok" |
| 492 | IF NOT Len(sWindow) THEN sWindow = "Closed" |
| 493 | IF NOT Len(sSensor) THEN sSensor = "Ok" |
| 494 | IF NOT Len(sWarn) THEN sWarn = "None" |
| 495 | ENDIF |
| 496 | IF bCULDebug THEN |
| 497 | Main.WriteDebugLog(("[CUL] FHT message received with address '") & sAddress & "' command '" & sCmd & "' (" & Hex(iCmd) & ") sval '" & sVal & "'" & IIf(iRSSI, " rssi: " & iRSSI, ""))
|
| 498 | IF Len(sWarn) THEN Main.WriteDebugLog(("[CUL] Warnings ") & sWarn)
|
| 499 | IF Len(sBatt) THEN Main.WriteDebugLog(("[CUL] Battery ") & sBatt)
|
| 500 | IF Len(sLowTemp) THEN Main.WriteDebugLog(("[CUL] LowTemp ") & sLowTemp)
|
| 501 | IF Len(sSensor) THEN Main.WriteDebugLog(("[CUL] Sensor ") & sSensor)
|
| 502 | IF Len(sWindow) THEN Main.WriteDebugLog(("[CUL] Window ") & sWindow)
|
| 503 | ENDIF |
| 504 | ENDIF |
| 505 | CASE "E" |
| 506 | ' E <Hex> |
| 507 | ' EM message. <Hex> is a hex string with the following format: |
| 508 | ' Ettaacc111122223333 |
| 509 | ' tt: type 01 = EM-1000S, 02 = EM-1000EM, 03 = EM-1000GZ |
| 510 | ' aa: address, depending on the type above 01: 01-04, 02: 05-08, 03: 09-12 |
| 511 | ' cc: counter, will be incremented by one for each message |
| 512 | ' 1111: cumulated value |
| 513 | ' 2222: last value(not set for type 2) |
| 514 | ' 3333: top value(not set for type 2) |
| 515 | sEMType = Chr(RecBuf[1]) & Chr(RecBuf[2]) |
| 516 | sAddress = Chr(RecBuf[3]) & Chr(RecBuf[4]) |
| 517 | sEMCumulValue = Chr(RecBuf[7]) & Chr(RecBuf[8]) & Chr(RecBuf[9]) & Chr(RecBuf[10]) |
| 518 | sMsgCounter = Chr(RecBuf[5]) & Chr(RecBuf[6]) |
| 519 | TRY sValue = Chr(RecBuf[11]) & Chr(RecBuf[12]) & Chr(RecBuf[13]) & Chr(RecBuf[14]) |
| 520 | TRY sEMPeakValue = Chr(RecBuf[15]) & Chr(RecBuf[16]) & Chr(RecBuf[17]) & Chr(RecBuf[18]) |
| 521 | |
| 522 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] EM message received sensor '") & aEMType[Val(sEMType)] & "' [" & sEMType & "]" & " with address '" & sAddress & "' cumulated value: " & sEMCumulValue & (" last: ") & sValue & (" top: ") & sEMPeakValue & (" msg count: ") & Val("&H" & sMsgCounter))
|
| 523 | |
| 524 | iDeviceId = Devices.Find(sAddress, Devices.FindInterface("CUL Interface"), "EM1000")
|
| 525 | ' update value |
| 526 | IF iDeviceId THEN Devices.ValueUpdate(iDeviceId, sEMCumulValue, sValue, sEMPeakValue, "") |
| 527 | CASE "V" |
| 528 | IF bCULDebug THEN Main.WriteDebugLog(("[CUL] Version string received."))
|
| 529 | CASE ELSE |
| 530 | Main.WriteDebugLog(("[CUL] Unknown/unsupported message format received!"))
|
| 531 | END SELECT |
| 532 | Main.ControlLed("CUL", "Off")
|
| 533 | |
| 534 | CATCH |
| 535 | Main.WriteDebugLog(("[CUL] ERROR: " & Error.Text & " at " & Error.Where & " Parsing CUL data packet: ") & DisplayPacket(RecBuf))
|
| 536 | |
| 537 | END |
| 538 | |
| 539 | ' converting CUL Hex IDs into ELV-4-Ids |
| 540 | PRIVATE SUB Hex2Four(sHex AS String) AS String |
| 541 | |
| 542 | DIM iCnt AS Integer |
| 543 | DIM sELV AS String |
| 544 | |
| 545 | FOR iCnt = 1 TO Len(sHex) |
| 546 | sELV &= Left(Str((Val("&H" & Mid(sHex, iCnt, 1)) / 4) + 1), 1)
|
| 547 | sELV &= (Val("&H" & Mid(sHex, iCnt, 1)) MOD 4) + 1
|
| 548 | NEXT |
| 549 | RETURN sELV |
| 550 | |
| 551 | END |
| 552 | |
| 553 | PRIVATE SUB FHTCode(iCode AS Byte) AS String |
| 554 | |
| 555 | SELECT CASE iCode |
| 556 | CASE &H00 |
| 557 | RETURN "actuator" |
| 558 | CASE &H01 |
| 559 | RETURN "actuator1" |
| 560 | CASE &H02 |
| 561 | RETURN "actuator2" |
| 562 | CASE &H03 |
| 563 | RETURN "actuator3" |
| 564 | CASE &H04 |
| 565 | RETURN "actuator4" |
| 566 | CASE &H05 |
| 567 | RETURN "actuator5" |
| 568 | CASE &H06 |
| 569 | RETURN "actuator6" |
| 570 | CASE &H07 |
| 571 | RETURN "actuator7" |
| 572 | CASE &H08 |
| 573 | RETURN "actuator8" |
| 574 | CASE &H14 |
| 575 | RETURN "mon-from1" |
| 576 | CASE &H15 |
| 577 | RETURN "mon-to1" |
| 578 | CASE &H16 |
| 579 | RETURN "mon-from2" |
| 580 | CASE &H17 |
| 581 | RETURN "mon-to2" |
| 582 | CASE &H18 |
| 583 | RETURN "tue-from1" |
| 584 | CASE &H19 |
| 585 | RETURN "tue-to1" |
| 586 | CASE &H1A |
| 587 | RETURN "tue-from2" |
| 588 | CASE &H1B |
| 589 | RETURN "tue-to2" |
| 590 | CASE &H1C |
| 591 | RETURN "wed-from1" |
| 592 | CASE &H1D |
| 593 | RETURN "wed-to1" |
| 594 | CASE &H1E |
| 595 | RETURN "wed-from2" |
| 596 | CASE &H1F |
| 597 | RETURN "wed-to2" |
| 598 | CASE &H20 |
| 599 | RETURN "thu-from1" |
| 600 | CASE &H21 |
| 601 | RETURN "thu-to1" |
| 602 | CASE &H22 |
| 603 | RETURN "thu-from2" |
| 604 | CASE &H23 |
| 605 | RETURN "thu-to2" |
| 606 | CASE &H24 |
| 607 | RETURN "fri-from1" |
| 608 | CASE &H25 |
| 609 | RETURN "fri-to1" |
| 610 | CASE &H26 |
| 611 | RETURN "fri-from2" |
| 612 | CASE &H27 |
| 613 | RETURN "fri-to2" |
| 614 | CASE &H28 |
| 615 | RETURN "sat-from1" |
| 616 | CASE &H29 |
| 617 | RETURN "sat-to1" |
| 618 | CASE &H2A |
| 619 | RETURN "sat-from2" |
| 620 | CASE &H2B |
| 621 | RETURN "sat-to2" |
| 622 | CASE &H2C |
| 623 | RETURN "sun-from1" |
| 624 | CASE &H2D |
| 625 | RETURN "sun-to1" |
| 626 | CASE &H2E |
| 627 | RETURN "sun-from2" |
| 628 | CASE &H2F |
| 629 | RETURN "sun-to2" |
| 630 | CASE &H3E |
| 631 | RETURN "mode" |
| 632 | CASE &H3F |
| 633 | RETURN "holiday1" |
| 634 | CASE &H40 |
| 635 | RETURN "holiday2" |
| 636 | CASE &H41 |
| 637 | RETURN "desired-temp" |
| 638 | CASE &H42 |
| 639 | RETURN "measured-low" |
| 640 | CASE &H43 |
| 641 | RETURN "measured-high" |
| 642 | CASE &H44 |
| 643 | RETURN "warnings" |
| 644 | CASE &H45 |
| 645 | RETURN "manu-temp" |
| 646 | CASE &H4B |
| 647 | RETURN "ack" |
| 648 | CASE &H53 |
| 649 | RETURN "can-xmit" |
| 650 | CASE &H54 |
| 651 | RETURN "can-rcv" |
| 652 | CASE &H60 |
| 653 | RETURN "year" |
| 654 | CASE &H61 |
| 655 | RETURN "month" |
| 656 | CASE &H62 |
| 657 | RETURN "day" |
| 658 | CASE &H63 |
| 659 | RETURN "hour" |
| 660 | CASE &H64 |
| 661 | RETURN "minute" |
| 662 | CASE &H65 |
| 663 | RETURN "report1" |
| 664 | CASE &H66 |
| 665 | RETURN "report2" |
| 666 | CASE &H69 |
| 667 | RETURN "ack2" |
| 668 | CASE &H7D |
| 669 | RETURN "start-xmit" |
| 670 | CASE &H7E |
| 671 | RETURN "end-xmit" |
| 672 | CASE &H82 |
| 673 | RETURN "day-temp" |
| 674 | CASE &H84 |
| 675 | RETURN "night-temp" |
| 676 | CASE &H85 |
| 677 | RETURN "lowtemp-offset" |
| 678 | CASE &H8A |
| 679 | RETURN "windowopen-temp" |
| 680 | CASE ELSE |
| 681 | RETURN "unknown" |
| 682 | END SELECT |
| 683 | |
| 684 | END |
| 685 | |
| 686 | PRIVATE SUB DisplayPacket(bBuf AS Byte[]) AS String |
| 687 | |
| 688 | DIM sMsg AS String |
| 689 | DIM iCnt AS Integer |
| 690 | |
| 691 | FOR iCnt = 0 TO iByteCount |
| 692 | sMsg &= Chr(bBuf[iCnt]) |
| 693 | NEXT |
| 694 | RETURN sMsg |
| 695 | |
| 696 | END |
| 697 | |
| 698 | ' implement properties |
| 699 | PRIVATE FUNCTION TCPHost_Read() AS String |
| 700 | |
| 701 | RETURN sTCPHost |
| 702 | |
| 703 | END |
| 704 | |
| 705 | PRIVATE SUB TCPHost_Write(Value AS String) |
| 706 | |
| 707 | sTCPHost = Value |
| 708 | |
| 709 | END |
| 710 | |
| 711 | PRIVATE FUNCTION TCPPort_Read() AS Integer |
| 712 | |
| 713 | RETURN iTCPPort |
| 714 | |
| 715 | END |
| 716 | |
| 717 | PRIVATE SUB TCPPort_Write(Value AS Integer) |
| 718 | |
| 719 | iTCPPort = Value |
| 720 | |
| 721 | END |
| 722 | |
| 723 | PRIVATE FUNCTION Interface_Read() AS String |
| 724 | |
| 725 | RETURN sInterface |
| 726 | |
| 727 | END |
| 728 | |
| 729 | PRIVATE SUB Interface_Write(Value AS String) |
| 730 | |
| 731 | sInterface = Value |
| 732 | |
| 733 | END |
| 734 | |
| 735 | PRIVATE FUNCTION Baud_Read() AS String |
| 736 | |
| 737 | RETURN sBaud |
| 738 | |
| 739 | END |
| 740 | |
| 741 | PRIVATE SUB Baud_Write(Value AS String) |
| 742 | |
| 743 | sBaud = Value |
| 744 | |
| 745 | END |
| 746 | |
| 747 | PRIVATE FUNCTION SerPort_Read() AS String |
| 748 | |
| 749 | RETURN sSerPort |
| 750 | |
| 751 | END |
| 752 | |
| 753 | PRIVATE SUB SerPort_Write(Value AS String) |
| 754 | |
| 755 | sSerPort = Value |
| 756 | |
| 757 | END |
| 758 | |
| 759 | PRIVATE FUNCTION CULDebug_Read() AS Boolean |
| 760 | |
| 761 | RETURN bCULDebug |
| 762 | |
| 763 | END |
| 764 | |
| 765 | PRIVATE SUB CULDebug_Write(Value AS Boolean) |
| 766 | |
| 767 | bCULDebug = Value |
| 768 | |
| 769 | END |
| 770 | |
| 771 | PRIVATE FUNCTION Model_Read() AS Integer |
| 772 | |
| 773 | RETURN iModel |
| 774 | |
| 775 | END |
| 776 | |
| 777 | PRIVATE SUB Model_Write(Value AS Integer) |
| 778 | |
| 779 | iModel = Value |
| 780 | |
| 781 | END |
