diff --git a/device/models.py b/device/models.py index 3bd5eeb..2aaa470 100644 --- a/device/models.py +++ b/device/models.py @@ -25,6 +25,7 @@ class Device: def __init__(self, *args, **kwargs): # the id is the chid of the device self.id = kwargs["id"] + self.uuid = kwargs.get("uuid") self.pk = self.id self.shortid = self.pk[:6].upper() self.algorithm = None @@ -103,6 +104,14 @@ class Device: self.evidences = [Evidence(u) for u in self.uuids] def get_last_evidence(self): + if self.last_evidence: + return + + if self.uuid: + import pdb; pdb.set_trace() + self.last_evidence = Evidence(self.uuid) + return + annotations = self.get_annotations() if not annotations.count(): return @@ -126,6 +135,8 @@ class Device: return False def last_uuid(self): + if self.uuid: + return self.uuid return self.uuids[0] def get_lots(self): @@ -263,41 +274,35 @@ class Device: @property def is_websnapshot(self): - if not self.last_evidence: - self.get_last_evidence() + self.get_last_evidence() return self.last_evidence.doc['type'] == "WebSnapshot" @property def last_user_evidence(self): - if not self.last_evidence: - self.get_last_evidence() + self.get_last_evidence() return self.last_evidence.doc['kv'].items() @property def manufacturer(self): - if not self.last_evidence: - self.get_last_evidence() + self.get_last_evidence() return self.last_evidence.get_manufacturer() @property def serial_number(self): - if not self.last_evidence: - self.get_last_evidence() + self.get_last_evidence() return self.last_evidence.get_serial_number() @property def type(self): + self.get_last_evidence() if self.last_evidence.doc['type'] == "WebSnapshot": return self.last_evidence.doc.get("device", {}).get("type", "") - if not self.last_evidence: - self.get_last_evidence() return self.last_evidence.get_chassis() @property def model(self): - if not self.last_evidence: - self.get_last_evidence() + self.get_last_evidence() return self.last_evidence.get_model() @property @@ -308,6 +313,5 @@ class Device: @property def components(self): - if not self.last_evidence: - self.get_last_evidence() + self.get_last_evidence() return self.last_evidence.get_components() diff --git a/device/views.py b/device/views.py index 3c7118c..c7c2b1f 100644 --- a/device/views.py +++ b/device/views.py @@ -1,4 +1,3 @@ -import json from django.http import JsonResponse from django.http import Http404 @@ -15,6 +14,7 @@ from dashboard.mixins import DashboardView, Http403 from evidence.models import Annotation from lot.models import LotTag from dpp.models import Proof +from dpp.api_dlt import PROOF_TYPE from device.models import Device from device.forms import DeviceFormSet @@ -104,7 +104,10 @@ class DetailsView(DashboardView, TemplateView): context = super().get_context_data(**kwargs) self.object.initial() lot_tags = LotTag.objects.filter(owner=self.request.user.institution) - dpps = Proof.objects.filter(uuid__in=self.object.uuids) + dpps = Proof.objects.filter( + uuid__in=self.object.uuids, + type=PROOF_TYPE["IssueDPP"] + ) context.update({ 'object': self.object, 'snapshot': self.object.get_last_evidence(), diff --git a/did/templates/device_did.html b/did/templates/device_did.html new file mode 100644 index 0000000..d3a0e2a --- /dev/null +++ b/did/templates/device_did.html @@ -0,0 +1,497 @@ + + + + + + {{ object.type }} + + + + + +
+ + +

{{ object.manufacturer }} {{ object.type }} {{ object.model }}

+ +
+
+ {% if manuals.details.logo %} + + {% endif %} +
+
+ {% if manuals.details.image %} + + {% endif %} +
+
+
+
+

Details

+
+
Phid
+
+
{{ object.id }}
+
+
+
+
Type
+
{{ object.type }}
+
+ + {% if object.is_websnapshot %} + {% for snapshot_key, snapshot_value in object.last_user_evidence %} +
+
{{ snapshot_key }}
+
{{ snapshot_value|default:'' }}
+
+ {% endfor %} + {% else %} +
+
Manufacturer
+
{{ object.manufacturer|default:'' }}
+
+
+
Model
+
{{ object.model|default:'' }}
+
+ {% if user.is_authenticated %} +
+
Serial Number
+
{{ object.serial_number|default:'' }}
+
+ {% endif %} + {% endif %} +
+ +
+

Identifiers

+ {% for chid in object.hids %} +
+
{{ chid|default:'' }}
+
+ {% endfor %} +
+
+

Components

+
+ {% for component in object.components %} +
+
+
+
{{ component.type }}
+

+ {% for component_key, component_value in component.items %} + {% if component_key not in 'actions,type' %} + {% if component_key != 'serialNumber' or user.is_authenticated %} + {{ component_key }}: {{ component_value }}
+ {% endif %} + {% endif %} + {% endfor %} +

+
+
+
+ {% endfor %} +
+ {% if manuals.icecat %} +
Icecat data sheet
+
+
+ {% if manuals.details.logo %} + + {% endif %} + {% if manuals.details.image %} + + {% endif %} + {% if manuals.details.pdf %} + {{ manuals.details.title }}
+ {% else %} + {{ manuals.details.title }}
+ {% endif %} +
+
+
+ +
+
+
+ {% for m in manuals.icecat %} +
+ {% if m.logo %} + + {% endif %} + {% if m.pdf %} + {{ m.title }}
+ {% else %} + {{ m.title }}
+ {% endif %} +
+ {% endfor %} +
+
+
+
+ {% endif %} + {% if manuals.laer %} +
+
+
Recycled Content
+ +
+
+ Metal +
+
+
+ +
{{ manuals.laer.0.metal }}% +
+
+
+
+
+
+ Plastic post Consumer +
+
+
+
{{ manuals.laer.0.plastic_post_consumer }}% +
+
+
+
+
+
+ Plastic post Industry +
+
+
+
{{ manuals.laer.0.plastic_post_industry }}% +
+
+
+
+
+
+ {% endif %} + + {% if manuals.energystar %} +
+
+
Energy spent
+ + {% if manuals.energystar.long_idle_watts %} +
+
+ Consumption when inactivity power function is activated (watts) +
+
+ {{ manuals.energystar.long_idle_watts }} +
+
+ {% endif %} + + {% if manuals.energystar.short_idle_watts %} +
+
+ Consumption when inactivity power function is not activated (watts) +
+
+ {{ manuals.energystar.short_idle_watts }} +
+
+ {% endif %} + + {% if manuals.energystar.sleep_mode_watts %} +
+
+ sleep_mode_watts + Consumption when computer goes into sleep mode (watts) +
+
+ {{ manuals.energystar.sleep_mode_watts }} +
+
+ {% endif %} + + {% if manuals.energystar.off_mode_watts %} +
+
+ Consumption when the computer is off (watts) +
+
+ {{ manuals.energystar.off_mode_watts }} +
+
+ {% endif %} + + {% if manuals.energystar.tec_allowance_kwh %} +
+
+ Power allocation for normal operation (kwh) +
+
+ {{ manuals.energystar.tec_allowance_kwh }} +
+
+ {% endif %} + + {% if manuals.energystar.tec_of_model_kwh %} +
+
+ Consumption of the model configuration (kwh) +
+
+ {{ manuals.energystar.tec_of_model_kwh }} +
+
+ {% endif %} + + {% if manuals.energystar.tec_requirement_kwh %} +
+
+ Energy allowance provided (kwh) +
+
+ {{ manuals.energystar.tec_requirement_kwh }} +
+
+ {% endif %} + + {% if manuals.energystar.work_off_mode_watts %} +
+
+ The lowest power mode which cannot be switched off (watts) +
+
+ {{ manuals.energystar.work_off_mode_watts }} +
+
+ {% endif %} + + {% if manuals.energystar.work_weighted_power_of_model_watts %} +
+
+ Weighted energy consumption from all its states (watts) +
+
+ {{ manuals.energystar.work_weighted_power_of_model_watts }} +
+
+ {% endif %} + +
+
+ {% endif %} + + + {% if manuals.ifixit %} +
+
+
+ +
+
+
+ {% for m in manuals.ifixit %} +
+ {% if m.image %} + + {% endif %} + {% if m.url %} + {{ m.title }}
+ {% else %} + {{ m.title }}
+ {% endif %} +
+ {% endfor %} +
+
+
+
+ {% endif %} + +{% if user.is_anonymous and not roles %} + +{% else %} + +{% endif %} + + + + diff --git a/did/templates/device_web.html b/did/templates/device_web.html deleted file mode 100644 index 8c607d3..0000000 --- a/did/templates/device_web.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - {{ object.type }} - - - - - -
-

{{ object.manufacturer }} {{ object.type }} {{ object.model }}

- -
-
-

Details

-
-
Phid
-
-
{{ object.id }}
-
-
-
-
Type
-
{{ object.type }}
-
- - {% if object.is_websnapshot %} - {% for snapshot_key, snapshot_value in object.last_user_evidence %} -
-
{{ snapshot_key }}
-
{{ snapshot_value|default:'' }}
-
- {% endfor %} - {% else %} -
-
Manufacturer
-
{{ object.manufacturer|default:'' }}
-
-
-
Model
-
{{ object.model|default:'' }}
-
- {% if user.is_authenticated %} -
-
Serial Number
-
{{ object.serial_number|default:'' }}
-
- {% endif %} - {% endif %} -
- -
-

Identifiers

- {% for chid in object.hids %} -
-
{{ chid|default:'' }}
-
- {% endfor %} -
-
-

Components

-
- {% for component in object.components %} -
-
-
-
{{ component.type }}
-

- {% for component_key, component_value in component.items %} - {% if component_key not in 'actions,type' %} - {% if component_key != 'serialNumber' or user.is_authenticated %} - {{ component_key }}: {{ component_value }}
- {% endif %} - {% endif %} - {% endfor %} -

-
-
-
- {% endfor %} -
-
- - - - - diff --git a/did/views.py b/did/views.py index 1caa081..e8ad5cd 100644 --- a/did/views.py +++ b/did/views.py @@ -1,14 +1,26 @@ +import json +import logging + from django.http import JsonResponse, Http404 from django.views.generic.base import TemplateView from device.models import Device +from dpp.models import Proof + + +logger = logging.getLogger('django') class PublicDeviceWebView(TemplateView): - template_name = "device_web.html" + template_name = "device_did.html" def get(self, request, *args, **kwargs): self.pk = kwargs['pk'] - self.object = Device(id=self.pk) + chid = self.pk.split(":")[0] + proof = Proof.objects.filter(signature=self.pk).first() + if proof: + self.object = Device(id=chid, uuid=proof.uuid) + else: + self.object = Device(id=chid) if not self.object.last_evidence: raise Http404 @@ -18,12 +30,24 @@ class PublicDeviceWebView(TemplateView): return super().get(request, *args, **kwargs) def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) + self.context = super().get_context_data(**kwargs) self.object.initial() - context.update({ - 'object': self.object + roles = [("Operator", "Operator")] + role = "Operator" + if self.request.user.is_anonymous: + roles = [] + role = None + self.context.update({ + 'object': self.object, + 'role': role, + 'roles': roles, + 'path': self.request.path, + 'last_dpp': "", + 'before_dpp': "", }) - return context + if not self.request.user.is_anonymous: + self.get_manuals() + return self.context @property def public_fields(self): @@ -58,3 +82,107 @@ class PublicDeviceWebView(TemplateView): device_data = self.get_device_data() return JsonResponse(device_data) + def get_manuals(self): + manuals = { + 'ifixit': [], + 'icecat': [], + 'details': {}, + 'laer': [], + 'energystar': {}, + } + try: + params = { + "manufacturer": self.object.manufacturer, + "model": self.object.model, + } + self.params = json.dumps(params) + manuals['ifixit'] = self.request_manuals('ifixit') + manuals['icecat'] = self.request_manuals('icecat') + manuals['laer'] = self.request_manuals('laer') + manuals['energystar'] = self.request_manuals('energystar') or {} + if manuals['icecat']: + manuals['details'] = manuals['icecat'][0] + except Exception as err: + logger.error("Error: {}".format(err)) + + self.context['manuals'] = manuals + self.parse_energystar() + + def parse_energystar(self): + if not self.context.get('manuals', {}).get('energystar'): + return + + # Defined in: + # https://dev.socrata.com/foundry/data.energystar.gov/j7nq-iepp + + energy_types = [ + 'functional_adder_allowances_kwh', + 'tec_allowance_kwh', + 'long_idle_watts', + 'short_idle_watts', + 'off_mode_watts', + 'sleep_mode_watts', + 'tec_of_model_kwh', + 'tec_requirement_kwh', + 'work_off_mode_watts', + 'work_weighted_power_of_model_watts', + ] + energy = {} + for field in energy_types: + energy[field] = [] + + for e in self.context['manuals']['energystar']: + for field in energy_types: + for k, v in e.items(): + if not v: + continue + if field in k: + energy[field].append(v) + + for k, v in energy.items(): + if not v: + energy[k] = 0 + continue + tt = sum([float(i) for i in v]) + energy[k] = round(tt / len(v), 2) + + self.context['manuals']['energystar'] = energy + + def request_manuals(self, prefix): + #TODO reimplement manuals service + response = { + "laer": [{"metal": 40, "plastic_post_consumer": 27, "plastic_post_industry": 34}], + "energystar": [{ + 'functional_adder_allowances_kwh': 180, + "long_idle_watts": 240, + "short_idle_watts": 120, + "sleep_mode_watts": 30, + "off_mode_watts": 3, + "tec_allowance_kwh": 180, + "tec_of_model_kwh": 150, + "tec_requirement_kwh": 220, + "work_off_mode_watts": 70, + "work_weighted_power_of_model_watts": 240 + }], + "ifixit": [ + { + "image": "https://guide-images.cdn.ifixit.com/igi/156EpI4YdQeVfVPa.medium", + "url": "https://es.ifixit.com/Gu%C3%ADa/HP+ProBook+450+G4+Back+Panel+Replacement/171196?lang=en", + "title": "HP ProBook 450 G4 Back Panel Replacement" + }, + { + "image": "https://guide-images.cdn.ifixit.com/igi/usTIqCKpuxVWC3Ix.140x105", + "url": "https://es.ifixit.com/Gu%C3%ADa/HP+ProBook+450+G4+Display+Assembly+Replacement/171101?lang=en", + "title": "Display Assembly Replacement" + } + ], + "icecat": [ + { + "logo": "https://images.icecat.biz/img/brand/thumb/1_cf8603f6de7b4c4d8ac4f5f0ef439a05.jpg", + "image": "https://guide-images.cdn.ifixit.com/igi/Q2nYjTIQfG6GaI5B.standard", + "pdf": "https://icecat.biz/rest/product-pdf?productId=32951710&lang=en", + "title": "HP ProBook 450 G3" + } + ] + } + return response.get(prefix, {})