ioext.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #!/usr/bin/python3 -u
  2. #
  3. import serial
  4. from time import sleep
  5. import os
  6. import sys
  7. import paho.mqtt.client as mqtt
  8. import json
  9. # --- CONFIGURATION ---
  10. import config
  11. # --- END CONFIGURATION ---
  12. # --- GLOBAL VARS ---
  13. noReceiveCount = 0 # increase everytime the serial readline times out (1s timeout)
  14. #getStatusCount = 0 # used as heartbeat, get status every 30s
  15. verbose = False
  16. debug = False
  17. quiet = True
  18. lastState_tk = None
  19. lastState_pir1 = None
  20. lastState_pir2 = None
  21. # --- END GLOBAL VARS ---
  22. if len(sys.argv) >= 2:
  23. if sys.argv[1] == "-q":
  24. verbose = False
  25. debug = False
  26. quiet = True
  27. #print("VERBOSE=ON")
  28. elif sys.argv[1] == "-v":
  29. verbose = True
  30. debug = False
  31. quiet = False
  32. #print("VERBOSE=ON")
  33. elif sys.argv[1] == "-d":
  34. verbose = True
  35. quiet = False
  36. debug = True
  37. #print("DEBUG=ON")
  38. def on_connect(client, userdata, flags, rc):
  39. if not quiet:
  40. print("MQTT connected with result code " + str(rc))
  41. #client.subscribe(mqtt_topic_cmd)
  42. #def on_message(client, userdata, msg):
  43. # if msg.topic == mqtt_topic_cmd:
  44. # payload = msg.payload.decode('ascii')
  45. # if payload == "status" or payload == "get conf" or payload == "clear" or payload == "open door" or payload.startswith("set prof ") or payload.startswith("set conf "):
  46. # if verbose:
  47. # print("serCmd: " + payload)
  48. # serCmd = payload + '\n'
  49. # ser.write(serCmd.encode('ascii'))
  50. # elif verbose:
  51. # print("unknown command:", payload)
  52. def touch(fname, times=None):
  53. with open(fname, 'a'):
  54. os.utime(fname, times)
  55. mqttc = mqtt.Client()
  56. mqttc.on_connect = on_connect
  57. #mqttc.on_disconnect = on_disconnect
  58. #mqttc.on_message = on_message
  59. mqttc.username_pw_set(config.mqtt_user, config.mqtt_password)
  60. mqttc.connect(config.mqtt_server, config.mqtt_port, 60)
  61. mqttc.loop_start()
  62. ser = serial.Serial(port=config.serialPort,
  63. baudrate = config.serialBaud,
  64. parity=serial.PARITY_NONE,
  65. stopbits=serial.STOPBITS_ONE,
  66. bytesize=serial.EIGHTBITS,
  67. timeout=config.serialTimeout)
  68. try:
  69. while True:
  70. ##ser.flushInput() ## attention truncates incoming strings if there is little time between them
  71. #read buffer until cr/lf
  72. serLine = ser.readline().strip()
  73. # catch exception on invalid char coming in: UnicodeDecodeError: 'ascii' codec can't decode byte 0xf4 in position 6: ordinal not in range(128)
  74. try:
  75. serLine = serLine.decode('ascii')
  76. except:
  77. serLine = ""
  78. # if there came something in...
  79. if(serLine):
  80. noReceiveCount = 0
  81. # touch status file if configured
  82. try:
  83. config.statusFile
  84. except:
  85. if debug:
  86. print("statusFile not defined")
  87. else:
  88. if config.statusFile is not None and config.statusFile != "":
  89. try:
  90. touch(config.statusFile)
  91. except:
  92. if debug:
  93. print("ERROR - could not touch statusFile '" + str(config.statusFile) + "'")
  94. else:
  95. if debug:
  96. print("statusFile not configured")
  97. if verbose:
  98. print ('RX: ' + repr(serLine)) #Echo the serial buffer bytes up to the CRLF back to screen
  99. mqttc.publish(config.mqtt_base_topic + "/RX", str(serLine), qos=0, retain=False)
  100. # Tuerkontakt
  101. if serLine.startswith('P2='):
  102. newState = None
  103. if serLine == "P2=L":
  104. newState = "OFF"
  105. elif serLine == "P2=H":
  106. newState = "ON"
  107. if newState is not None and lastState_tk != newState:
  108. lastState_tk = newState
  109. mqttc.publish(config.mqtt_topic_tuerkontakt, newState, qos=0, retain=False)
  110. # PIR #1
  111. if serLine.startswith('P3='):
  112. newState = None
  113. if serLine == "P3=L":
  114. newState = "OFF"
  115. elif serLine == "P3=H":
  116. newState = "ON"
  117. if newState is not None and lastState_pir1 != newState:
  118. lastState_pir1 = newState
  119. mqttc.publish(config.mqtt_topic_pir1, newState, qos=0, retain=False)
  120. # PIR #2
  121. if serLine.startswith('P4='):
  122. newState = None
  123. if serLine == "P4=L":
  124. newState = "OFF"
  125. elif serLine == "P4=H":
  126. newState = "ON"
  127. if newState is not None and lastState_pir2 != newState:
  128. lastState_pir2 = newState
  129. mqttc.publish(config.mqtt_topic_pir2, newState, qos=0, retain=False)
  130. # DHT TH sensor
  131. # {"T":26.60,"H":36}
  132. if serLine.startswith('{"T":'):
  133. th = json.loads(serLine)
  134. t = round(float(th["T"]), 1)
  135. h = int(th["H"])
  136. if t >= -20 and t <= 50:
  137. mqttc.publish(config.mqtt_topic_out_temp, str(t), qos=0, retain=False)
  138. if h >= 0 and h <= 100:
  139. mqttc.publish(config.mqtt_topic_out_hum, str(h), qos=0, retain=False)
  140. # nothing came in this time...
  141. else:
  142. noReceiveCount += 1
  143. if debug:
  144. print("noReceiveCount=" + str(noReceiveCount))
  145. # quit script if nothing has been received for some time - will be restarted by systemd
  146. if noReceiveCount >= config.quitOnNoReceiveTimeout:
  147. quit()
  148. except KeyboardInterrupt:
  149. print('\n')