import dateutil.parser
from datetime import datetime, timezone
from requests.exceptions import ConnectionError
from rest_framework import serializers
from influxdb import InfluxDBClient
from django.conf import settings
from django.db.models.query import QuerySet
from influxdb.exceptions import InfluxDBClientError
from ..models import Node, Connection, Device, ImageLayer
[docs]class DeviceSerializer(serializers.ModelSerializer):
#node = serializers.SerializerMethodField('_nodes')
#def _nodes(self, obj):
# return str(obj.nodes) if len(obj.nodes) else None
class Meta:
model = Device
fields = ['pk', 'name', 'nodes', 'template', 'ip', 'hostname', 'mac', 'mqtt_topic', 'admin_link']
[docs]class NodeSerializer(serializers.ModelSerializer):
age = serializers.SerializerMethodField('_age')
power = serializers.SerializerMethodField('_power')
kilowatthour = serializers.SerializerMethodField('_kilowatthour')
_influx_data = {}
def _set_influx(self, key, node, value):
if key not in self._influx_data:
self._influx_data[key] = {}
self._influx_data[key][node.pk] = value
def _get_influx(self, obj, key):
try:
return self._influx_data[key][obj.pk]
except (KeyError, Device.DoesNotExist) as e:
return -1
def _age(self, obj):
return self._get_influx(obj, "age")
def _power(self, obj):
return self._get_influx(obj, "power")
def _kilowatthour(self, obj):
return self._get_influx(obj, "kilowatt_hour")
[docs] def __init__(self, *args, **kwargs):
super(NodeSerializer, self).__init__(*args, **kwargs)
if len(args) < 1:
return
influx = InfluxDBClient(settings.INFLUXDB_HOST, settings.INFLUXDB_PORT, settings.INFLUXDB_USERNAME, settings.INFLUXDB_PASSWORD, settings.INFLUXDB_DATABASE_NAME)
for node in (args[0] if type(args[0]) is QuerySet else [args[0], ]):
try:
point = next(influx.query('SELECT last("Power") FROM "%s"' % node.id).get_points())
age = (datetime.now(timezone.utc) - dateutil.parser.parse(point["time"])).total_seconds()
self._set_influx('age', node, int(age))
self._set_influx('power', node, int(point["last"]))
#points = influx.query('SELECT sum(*) FROM (SELECT sum("Power") / count("Power") FROM "%s" group by time(1h)) group by time(1h)' % node.id).get_points()
#for point in points:
# print(point)
# self.devices_kilowatt_hour[device.pk] = point['sum_sum_count']
except (StopIteration, ConnectionError, InfluxDBClientError) as e:
print('EXCEPTION ' + str(node))
pass
influx.close()
[docs] def update(self, instance, validated_data):
#try:
# nested_data = validated_data.pop('device')
# print(nested_data)
# device = Device.objects.get(pk=nested_data.pk)
# print(device)
# device.node = instance
# device.save()
#except KeyError:
# pass
return super(NodeSerializer, self).update(instance, validated_data)
class Meta:
model = Node
fields = ['pk', 'name', 'age', 'power', 'kilowatthour', 'warning_level', 'shutdown_level', 'cut_power', 'device', 'latitude', 'longitude']
extra_kwargs = {'device': {'required': False}}
[docs]class ConnectionSerializer(serializers.ModelSerializer):
class Meta:
model = Connection
fields = ['pk', 'geojson']
[docs]class ImageLayerSerializer(serializers.ModelSerializer):
class Meta:
model = ImageLayer
fields = ["pk", "image", "latitude1", "longitude1", "latitude2", "longitude2", "latitude3", "longitude3"]
read_only_fields = ['image']
[docs]class ImageLayerUploadSerializer(serializers.ModelSerializer):
class Meta:
model = ImageLayer
fields = ['image']
[docs]class StatsSerializer(serializers.Serializer):
nodes = NodeSerializer(many=True)
class Meta:
read_only_fields = ['nodes', ]