Skip to content

Commit ddc4d58

Browse files
committed
Merge branch 'main' of github.com:Aiky30/shed-pi into feature/paginated-endpoints
2 parents c16c789 + e9f1aeb commit ddc4d58

43 files changed

Lines changed: 842 additions & 89 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,30 @@
55
A package to run a Raspberry Pi in an outbuilding such as a garden shed, for the internet of sheds.
66

77
Automated use cases:
8+
89
- Weather station
910
- Garden lighting
1011
- Security
1112

13+
## Design Principles
14+
15+
The Hub contains a Protocol, and can utilise modules
16+
A device contains a protocol, and can utilise modules
17+
1218
## TODO:
19+
1320
1. Fix: Bug: The script startup gets an incorrect time (Hasn't yet got the internet time)
1421
2. Instructions on pinout
22+
3. Tests for the utils and base protocol
23+
4. Extend Baseprotocol with a reusable run method
24+
5. General Integration test for the logger using a fake module
25+
6. Test default endpoint address settings work in theory, because the test above overrides them
26+
7. Device startup and shutdown needs a unit test
27+
8. Temp probe should be a fixture
28+
9. CPU temp probe should be a fixture
1529

1630
### Wish list:
31+
1732
- Poetry (Not started)
1833
- ASGI backend server (Daphne)
1934
- Native webcomponent FE with Bootstrap
@@ -40,6 +55,7 @@ sudo raspi-config
4055
3. Agree to installing the 1-Wire script
4156

4257
4. Reboot
58+
4359
```shell
4460
sudo reboot
4561
```
@@ -51,6 +67,7 @@ ls /sys/bus/w1/devices/
5167
```
5268

5369
Check the value read, be sure to change "28-000003ebbf13" to the values listed above:
70+
5471
```shell
5572
cat /sys/bus/w1/devices/28-000003ebbf13/w1_slave
5673
```
@@ -67,20 +84,21 @@ With the contents
6784

6885
```ini
6986
[Unit]
70-
Description=Shed-Pi
71-
After=multi-user.target
72-
StartLimitIntervalSec=0
87+
Description = Shed-Pi
88+
After = multi-user.target
89+
StartLimitIntervalSec = 0
7390
7491
[Service]
75-
Type=simple
76-
ExecStart=/usr/bin/python3 /home/shed-pi/temp_logger.py
77-
StandardInput=tty-force
92+
Type = simple
93+
ExecStart = /usr/bin/python3 /home/shed-pi/temp_logger.py
94+
StandardInput = tty-force
7895
7996
[Install]
80-
WantedBy=multi-user.target
97+
WantedBy = multi-user.target
8198
```
8299

83100
Enable the service, (CAVEAT: didn't work when manually starting, works on reboot)
101+
84102
```shell
85103
sudo systemctl daemon-reload
86104
sudo systemctl enable shed-pi.service
@@ -89,6 +107,7 @@ sudo systemctl status shed-pi.service
89107
```
90108
91109
Read the logs
110+
92111
```shell
93112
tail -f /var/log/shed-pi.log
94113
```
@@ -100,18 +119,19 @@ tail -f /var/log/shed-pi.log
100119
Install pre-commit: https://pre-commit.com/
101120
102121
Configure precommit on your local git for the project by running the following at the root of the project:
122+
103123
```shell
104124
pre-commit install
105125
```
106-
Pre-commit will then automatically run for your changes at commit time.
107126
127+
Pre-commit will then automatically run for your changes at commit time.
108128
109129
To run the pre-commit config manually, run:
130+
110131
```shell
111132
pre-commit run --all-files
112133
```
113134
114-
115135
## Release
116136
117137
Generate the release

requirements.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
asgiref==3.7.2
22
attrs==23.2.0
3+
black==24.2.0
34
build==0.10.0
5+
certifi==2024.2.2
46
cfgv==3.4.0
7+
charset-normalizer==3.3.2
8+
click==8.1.7
59
distlib==0.3.8
610
Django==5.0.1
711
djangorestframework==3.14.0
@@ -10,11 +14,14 @@ factory-boy==3.3.0
1014
Faker==22.5.0
1115
filelock==3.13.1
1216
identify==2.5.33
17+
idna==3.6
1318
iniconfig==2.0.0
1419
jsonschema==4.21.1
1520
jsonschema-specifications==2023.12.1
21+
mypy-extensions==1.0.0
1622
nodeenv==1.8.0
1723
packaging==23.1
24+
pathspec==0.12.1
1825
platformdirs==4.1.0
1926
pluggy==1.4.0
2027
pre-commit==3.6.0
@@ -25,10 +32,12 @@ python-dateutil==2.8.2
2532
pytz==2023.3.post1
2633
PyYAML==6.0.1
2734
referencing==0.32.1
35+
requests==2.31.0
2836
rpds-py==0.17.1
2937
setuptools-scm==7.1.0
3038
six==1.16.0
3139
sqlparse==0.4.4
3240
tomli==2.0.1
3341
typing_extensions==4.7.1
42+
urllib3==2.2.1
3443
virtualenv==20.25.0

shedpi_hub_dashboard/admin.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from typing import ClassVar
2+
13
from django.contrib import admin
4+
from django.contrib.admin.options import InlineModelAdmin
25

36
from .models import Device, DeviceModule, DeviceModuleReading
47

@@ -8,11 +11,28 @@ class DeviceAdmin(admin.ModelAdmin):
811
list_display = ("id", "name")
912

1013

14+
class DeviceModuleReadingInlineAdmin(admin.TabularInline):
15+
model = DeviceModuleReading
16+
extra = 0
17+
can_delete = False
18+
19+
# TODO: trying to limit the inline with pagination
20+
# list_per_page = 5 # No of records per page
21+
#
22+
# def get_queryset(self, request):
23+
# # TODO: return type -> QuerySet
24+
#
25+
# queryset = super().get_queryset(request)
26+
#
27+
# return queryset[:5]
28+
29+
1130
@admin.register(DeviceModule)
1231
class DeviceModuleAdmin(admin.ModelAdmin):
13-
pass
32+
inlines: ClassVar[list[InlineModelAdmin]] = [DeviceModuleReadingInlineAdmin]
1433

1534

1635
@admin.register(DeviceModuleReading)
1736
class DeviceModuleReadingAdmin(admin.ModelAdmin):
1837
list_display = ("id", "device_module_id", "created_at")
38+
list_filter = ("device_module_id",)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0.1 on 2024-04-19 18:32
2+
3+
import django.utils.timezone
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
dependencies = [
9+
("shedpi_hub_dashboard", "0001_initial"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="devicemodulereading",
15+
name="created_at",
16+
field=models.DateTimeField(default=django.utils.timezone.now),
17+
),
18+
]

shedpi_hub_dashboard/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import uuid
22

33
from django.db import models
4+
from django.utils import timezone
45
from jsonschema import validate
56

67
from shedpi_hub_dashboard.forms.fields import PrettyJsonField
@@ -37,7 +38,7 @@ class DeviceModuleReading(models.Model):
3738
help_text="A device whose readings were collected.",
3839
)
3940
data = PrettyJsonField(null=True, blank=True)
40-
created_at = models.DateTimeField(auto_now_add=True)
41+
created_at = models.DateTimeField(default=timezone.now)
4142

4243
def validate_data(self) -> None:
4344
"""

shedpi_hub_dashboard/static/shedpi_hub_dashboard/js/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ section.append(tableContainer);
7373
let loadTableData = function (deviceModuleId) {
7474

7575
// const url = section.getAttribute("data-json-feed")
76-
const url = "http://localhost:8000//api/v1/device-module-readings/"
76+
const url = window.location.origin + "/api/v1/device-module-readings/"
7777
const endpoint = new URL(url);
7878
endpoint.searchParams.append("device_module", deviceModuleId);
79+
endpoint.searchParams.append("format", "json");
7980

8081
// FIXME: Need data output and need headings from Schema
8182

shedpi_hub_dashboard/tests/integration/__init__.py

Whitespace-only changes.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import json
2+
from unittest.mock import Mock, patch
3+
4+
import pytest
5+
from rest_framework import status
6+
7+
from shedpi_hub_dashboard.models import DeviceModuleReading
8+
from shedpi_hub_dashboard.tests.utils.factories import (
9+
DeviceModuleFactory,
10+
)
11+
from standalone_modules.shed_pi_module_utils.data_submission import (
12+
ReadingSubmissionService,
13+
)
14+
from standalone_modules.temperature_module.temperature_probe import (
15+
TempProbe,
16+
)
17+
18+
19+
@patch("standalone_modules.temperature_module.temperature_probe.Path")
20+
@pytest.mark.django_db
21+
def test_temperature_module_reading_submission(mocked_path, live_server):
22+
schema = {
23+
"$id": "https://example.com/person.schema.json",
24+
"$schema": "https://json-schema.org/draft/2020-12/schema",
25+
"title": "Reading",
26+
"type": "object",
27+
"properties": {
28+
"temperature": {"type": "string", "description": "The Temperature"},
29+
},
30+
}
31+
device_module = DeviceModuleFactory(schema=schema)
32+
submission_service = ReadingSubmissionService()
33+
# Override the serviuce url
34+
submission_service.base_url = live_server.url
35+
36+
probe = TempProbe(submission_service=submission_service)
37+
# Override the module id
38+
probe.device_id = device_module.id
39+
40+
probe.read_temp_raw = Mock(
41+
return_value=[
42+
"YES",
43+
"t=12345",
44+
]
45+
)
46+
47+
response = probe.submit_reading()
48+
49+
assert response.status_code == status.HTTP_201_CREATED
50+
51+
response_data = json.loads(response.text)
52+
53+
assert "created_at" in response_data
54+
assert DeviceModuleReading.objects.filter(device_module=device_module).count() == 1

shedpi_hub_dashboard/tests/unit/__init__.py

Whitespace-only changes.

shedpi_hub_dashboard/tests/test_endpoints.py renamed to shedpi_hub_dashboard/tests/unit/test_endpoints.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from rest_framework.exceptions import ValidationError
66
from rest_framework.reverse import reverse
77

8+
from shedpi_hub_dashboard.models import DeviceModuleReading
89
from shedpi_hub_dashboard.tests.utils.factories import (
910
DeviceModuleFactory,
1011
DeviceModuleReadingFactory,
@@ -149,3 +150,4 @@ def test_device_module_reading_submission(client):
149150

150151
assert response.status_code == status.HTTP_201_CREATED
151152
assert response.data["data"] == data
153+
assert DeviceModuleReading.objects.filter(device_module=device_module).count() == 1

0 commit comments

Comments
 (0)