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.

Statistics
| Revision:

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