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.9KB

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