Projet de remplacement du "RPiPasserelle" d'Otec.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cli.py 7.0KB

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