|  | @ -201,3 +201,78 @@ class MqttOutputPlugin(OutputPluginFactory): | 
			
		
	
		
		
			
				
					|  |  |             self.client.publish(f'{topic}/pf', data['powerfactor']) |  |  |             self.client.publish(f'{topic}/pf', data['powerfactor']) | 
			
		
	
		
		
			
				
					|  |  |         self.client.publish(f'{topic}/frequency', data['frequency']) |  |  |         self.client.publish(f'{topic}/frequency', data['frequency']) | 
			
		
	
		
		
			
				
					|  |  |         self.client.publish(f'{topic}/temperature', data['temperature']) |  |  |         self.client.publish(f'{topic}/temperature', data['temperature']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | try: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     import requests | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     import time | 
			
		
	
		
		
			
				
					|  |  |  |  |  | except ModuleNotFoundError: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     pass | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | class VolkszaehlerOutputPlugin(OutputPluginFactory): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     def __init__(self, config, **params): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         """ | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         Initialize VolkszaehlerOutputPlugin | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         """ | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         super().__init__(**params) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         self.baseurl = config.get('url', 'http://localhost/middleware/') | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         self.channels = dict() | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         for channel in config.get('channels', []): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             uid = channel.get('uid') | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             ctype = channel.get('type') | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             if uid and ctype: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 self.channels[ctype] = uid | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     def store_status(self, response, **params): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         """ | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         Publish StatusResponse object | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         :param hoymiles.decoders.StatusResponse response: StatusResponse object | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         :raises ValueError: when response is not instance of StatusResponse | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         """ | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         if not isinstance(response, StatusResponse): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             raise ValueError('Data needs to be instance of StatusResponse') | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         if len(self.channels) == 0: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             return | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         data = response.__dict__() | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         ts = int(round(data['time'].timestamp() * 1000)) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         # AC Data | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         phase_id = 0 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         for phase in data['phases']: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'ac_power{phase_id}', phase['power']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'ac_voltage{phase_id}', phase['voltage']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'ac_current{phase_id}', phase['current']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             phase_id = phase_id + 1 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         # DC Data | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         string_id = 0 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         for string in data['strings']: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'dc_power{string_id}', string['power']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'dc_voltage{string_id}', string['voltage']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'dc_current{string_id}', string['current']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'dc_total{string_id}', string['energy_total']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'dc_daily{string_id}', string['energy_daily']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             string_id = string_id + 1 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         # Global | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         if data['powerfactor'] is not None: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.try_publish(ts, f'powerfactor', data['powerfactor']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         self.try_publish(ts, f'frequency', data['frequency']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         self.try_publish(ts, f'temperature', data['temperature']) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     def try_publish(self, ts, ctype, value): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         if not ctype in self.channels: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             return | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         uid = self.channels[ctype] | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         url = f'{self.baseurl}/data/{uid}.json?operation=add&ts={ts}&value={value}' | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         try: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             r = requests.get(url) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             if r.status_code != 200: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 raise ValueError('Could not send request (%s)' % url) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         except ConnectionError as e: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             raise ValueError('Could not send request (%s)' % e) | 
			
		
	
	
		
		
			
				
					|  | 
 |