Projet de remplacement du "RPiPasserelle" d'Otec.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cli.py 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #!/usr/bin/env python3
  2. # builtins
  3. import click
  4. from datetime import datetime
  5. import importlib
  6. import time
  7. import json
  8. import os
  9. import re
  10. import socket
  11. import sys
  12. import time
  13. import urllib
  14. import uvicorn
  15. import requests
  16. from pyheatpump.logger import logger_init
  17. from pyheatpump.models import *
  18. CONTEXT_SETTINGS={
  19. 'default_map':{'run': {}}
  20. }
  21. @click.group(invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
  22. @click.option('--version', is_flag=True)
  23. @click.pass_context
  24. def cli(ctx, version):
  25. """
  26. if version:
  27. from pyheatpump import version
  28. return click.echo(pyheatpump.version())
  29. """
  30. pass
  31. @click.option('--host', default=None)
  32. @click.option('--port', default=None)
  33. @cli.command()
  34. def run(host, port):
  35. logger = logger_init()
  36. from .config import (API_HOST, API_PORT)
  37. if not host:
  38. host = API_HOST
  39. if not port:
  40. port = API_PORT
  41. log_level = 'info'
  42. click.echo('Launching PyHeatpump application')
  43. uvicorn.run('pyheatpump.app:application',
  44. host=host,
  45. port=int(port),
  46. log_level=log_level,
  47. workers=1)
  48. def fetch(types=[]):
  49. logger = logger_init()
  50. from pyheatpump import modbus
  51. try:
  52. if len(types) == 0:
  53. var_types = VariableType.getall()
  54. else:
  55. var_types = {}
  56. for label, var_type in VariableType.getall().items():
  57. if label in type or var_type.slabel in type:
  58. var_types[label] = var_type
  59. # Analog - float
  60. if 'Analog' in var_types.keys():
  61. analog = var_types['Analog']
  62. logger.info('Read analog variables in registers [{}, {}]'.format(
  63. analog.start_address, analog.end_address
  64. ))
  65. res = modbus.read_holding_registers(analog.start_address, analog.end_address)
  66. logger.debug(f'analog length : {len(res)}')
  67. for r in range(len(res)):
  68. var = Variable(**{
  69. 'type': analog,
  70. 'address': r + analog.start_address})
  71. if not var.exists():
  72. logger.info('Insert variable {}:{}'.format(
  73. var.type, var.address))
  74. var.insert()
  75. val = VariableValue(**{
  76. 'type': var.type,
  77. 'address': var.address,
  78. 'value': res[r]})
  79. val.insert()
  80. # Integer - int
  81. if 'Integer' in var_types.keys():
  82. integer = var_types['Integer']
  83. logger.info('Read integer variables in registers [{}, {}]'.format(
  84. integer.start_address, integer.end_address
  85. ))
  86. res = modbus.read_holding_registers(integer.start_address, integer.end_address)
  87. logger.debug(f'integer length : {len(res)}')
  88. for r in range(len(res)):
  89. var = Variable(**{
  90. 'type': integer,
  91. 'address': r + integer.start_address})
  92. if not var.exists():
  93. logger.info('Insert variable {}:{}'.format(
  94. var.type, var.address))
  95. var.insert()
  96. val = VariableValue(**{
  97. 'type': var.type,
  98. 'address': var.address,
  99. 'value': res[r]})
  100. val.insert()
  101. # Digital - bool
  102. if 'Digital' in var_types.keys():
  103. digital = var_types['Digital']
  104. logger.info('Read digital variables in coils [{}, {}]'.format(
  105. digital.start_address, digital.end_address
  106. ))
  107. res = modbus.read_coils(digital.start_address, digital.end_address)
  108. logger.debug(f'digital length : {len(res)}')
  109. for r in range(len(res)):
  110. var = Variable(**{
  111. 'type': digital,
  112. 'address': r + digital.start_address})
  113. if not var.exists():
  114. logger.info('Insert variable {}:{}'.format(
  115. var.type, var.address))
  116. var.insert()
  117. val = VariableValue(**{
  118. 'type': var.type,
  119. 'address': var.address,
  120. 'value': res[r]})
  121. val.insert()
  122. logger.info('Successfully read all variables')
  123. except Exception as exc:
  124. logger.error(exc)
  125. if modbus.serial_conn:
  126. modbus.serial_conn.close()
  127. @click.option('--since', is_flag=True)
  128. @cli.command()
  129. def supervise(since):
  130. logger = logger_init()
  131. build_url = lambda d: '{scheme}://{hostname}:{port}{path}'.format(**d)
  132. from .config import config, mac_address_init, get_last_update, set_last_update
  133. mac_address = config.get('heatpump','mac_address')
  134. if not re.match('^(([0-9a-f]{2}):?){6}$', mac_address, re.I):
  135. mac_address = mac_address_init()
  136. from .models.heatpump import Heatpump
  137. if not since:
  138. last_update = 0
  139. else:
  140. last_update = get_last_update()
  141. base_url = {
  142. 'scheme':config.get('supervisor', 'scheme'),
  143. 'hostname':config.get('supervisor', 'host'),
  144. 'port':config.getint('supervisor', 'port')
  145. }
  146. get_path = '/'.join((
  147. config.get('supervisor', 'get_path'),
  148. Heatpump(mac_address).macformat
  149. ))
  150. get_url = {
  151. **base_url,
  152. **{'path': get_path}
  153. }
  154. try:
  155. get_resp = requests.get(
  156. url=build_url(get_url),
  157. verify=False
  158. )
  159. except socket.gaierror as exc:
  160. logger.error('Socket error : %s', exc)
  161. sys.exit(-1)
  162. control_data = get_resp.json()
  163. if Heatpump(mac_address).control(control_data):
  164. logger.info('GET to supervisor succeded : updated values')
  165. else:
  166. logger.warn('Unable to set data from supervisor\n{}'.format(control_data))
  167. # Récupération de toutes les variables en modbus
  168. fetch()
  169. post_packets = [
  170. Heatpump(mac_address, last_update, ['Analog']).packet,
  171. Heatpump(mac_address, last_update, ['Digital']).packet,
  172. Heatpump(mac_address, last_update, ['Integer']).packet
  173. ]
  174. post_url = {
  175. **base_url,
  176. **{'path': config.get('supervisor', 'post_path')}
  177. }
  178. logger.info(build_url(post_url))
  179. for packet in post_packets:
  180. logger.debug('Will send %s', packet)
  181. post_resp = requests.post(
  182. url=build_url(post_url),
  183. json=packet,
  184. verify=False,
  185. timeout=200
  186. )
  187. if post_resp.status_code == 200:
  188. logger.info('POST to supervisor succeeded')
  189. continue
  190. logger.info('POST to supervisor failed')
  191. set_last_update(int(datetime.now().strftime('%s')))