Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ This device runs on a Raspberry Pi Pico W and provides physical input and output

Further documentation can be found [in the smibhid repo](https://github.com/somakeit/smibhid/).

### SMIBHID APIs

> [!IMPORTANT]
> The `device-hostname` header is a mandatory field for the SMIBHID APIs

#### Pushing Sensor Log Data to SMIB DB

The following us a CURL command that "posts" the provided sensor data to SMIB.

```bash
curl -X POST http://localhost/smib/event/smibhid_sensor_log ^
-H "Content-Type: application/json" ^
-H "device-hostname: smibhid-example" ^
-d "[{\"human_timestamp\": \"2025-04-03T21:42:58Z\", \"data\": {\"SCD30\": {\"relative_humidity\": 0, \"temperature\": 0, \"co2\": 0}, \"BME280\": {\"pressure\": 1019.3, \"humidity\": 48.7, \"temperature\": 20.03}}, \"timestamp\": 1743716578}, {\"timestamp\": 1743791084, \"data\": {\"SCD30\": {\"co2\": 1548.1, \"temperature\": 26.3, \"relative_humidity\": 52.9}, \"BME280\": {\"pressure\": 632, \"humidity\": 57.64, \"temperature\": 23.05}}, \"human_timestamp\": \"2025-04-04T18:24:44Z\"}]"
```

## Legacy SMIB Commands
Currently, the old [SMIB Commands](https://github.com/somakeit/smib-commands) do not work with the new SMIB.

Expand Down
54 changes: 48 additions & 6 deletions smib/slack/plugins/space/smibhid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
__author__ = "Sam Cork"

from datetime import datetime
from datetime import UTC
from logging import Logger
from pprint import pformat

Expand All @@ -13,21 +14,27 @@
from smib.slack.db import database
from mogo.connection import Connection
from smib.common.utils import http_bolt_response
from .models.api import UILogs as ApiUILogs, UILog as ApiUILog
from .models.db import UILog as DbUILog
from .models.api.ui_logs import UILogs as ApiUILogs, UILog as ApiUILog
from .models.db.ui_logs import UILog as DbUILog

from .models.api.sensor_data import SensorLogs as ApiSensorLogs, SensorLog as ApiSensorLog
from .models.db.sensor_data import SensorLog as DbSensorLog

from slack_bolt.request import BoltRequest

app: CustomApp = inject("SlackApp")

def extract_device_hostname(request: BoltRequest):
device_hostname, *_ = request.headers.get('device-hostname', [None])
return device_hostname

@app.event("http_post_smibhid_ui_log")
@http_bolt_response
def on_smibhid_ui_log_post(event: dict, context: dict, ack: callable, request: BoltRequest):
ack()
logger: Logger = context.get('logger')

device_hostname, *_ = request.headers.get('device-hostname', None)
device_hostname = extract_device_hostname(request)
device_ip = event['request']['ip']

data = event.get("data", [])
Expand All @@ -44,21 +51,56 @@ def on_smibhid_ui_log_post(event: dict, context: dict, ack: callable, request: B
logger.warning(e)
return 400, {}

save_api_logs_to_db(ui_logs, device_ip, device_hostname)
save_api_ui_logs_to_db(ui_logs, device_ip, device_hostname)


@database()
def save_api_logs_to_db(api_logs: ApiUILogs, device_ip: str, device_hostname: str | None):
def save_api_ui_logs_to_db(api_logs: ApiUILogs, device_ip: str, device_hostname: str | None):
for api_log in api_logs:
api_log: ApiUILog

db_log = DbUILog()

db_log.timestamp = datetime.utcfromtimestamp(api_log.timestamp)
db_log.timestamp = datetime.fromtimestamp(api_log.timestamp, tz=UTC)
db_log.type = api_log.type
db_log.event = api_log.event.dict()

db_log.device_hostname = device_hostname
db_log.device_ip = device_ip

db_log.save()

@app.event("http_post_smibhid_sensor_log")
@http_bolt_response
def on_smibhid_sensor_data_post(event: dict, context: dict, ack: callable, request: BoltRequest):
ack()
logger: Logger = context.get('logger')

device_hostname = extract_device_hostname(request)
device_ip = event['request']['ip']
data = event.get("data", [])
if not data:
logger.info("No logs received in request")
return

logger.debug(pformat(data))

try:
sensor_logs = ApiSensorLogs(logs=data)
logger.debug(sensor_logs)
except ValidationError as e:
logger.warning(e)
return 400, {}

save_api_sensor_logs_to_db(sensor_logs, device_ip, device_hostname)

@database()
def save_api_sensor_logs_to_db(api_logs: ApiSensorLogs, device_ip: str, device_hostname: str | None):
for api_log in api_logs:
api_log: ApiSensorLog
db_log = DbSensorLog()
db_log.timestamp = datetime.fromtimestamp(api_log.timestamp, tz=UTC)
db_log.data = api_log.data.model_dump()
db_log.device_hostname = device_hostname
db_log.device_ip = device_ip
db_log.save()
Empty file.
20 changes: 20 additions & 0 deletions smib/slack/plugins/space/smibhid/models/api/sensor_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pydantic import BaseModel, RootModel


class SensorData(RootModel):
root: dict[str, float | int]

class ModuleData(RootModel):
root: dict[str, SensorData]

class SensorLog(BaseModel):
timestamp: int
human_timestamp: str
data: ModuleData


class SensorLogs(BaseModel):
logs: list[SensorLog]

def __iter__(self):
yield from self.logs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,4 @@ class UILogs(BaseModel):
ui_logs: list[UILog]

def __iter__(self):
yield from self.ui_logs



yield from self.ui_logs
Empty file.
11 changes: 11 additions & 0 deletions smib/slack/plugins/space/smibhid/models/db/sensor_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from datetime import datetime
from smib.slack.db import Model, Field


class SensorLog(Model):
_name = "smibhid-sensor-logs"

timestamp = Field[datetime](datetime, required=True)
data = Field[dict[str, dict[str, float | int]]](dict, required=True)
device_hostname = Field[str](str)
device_ip = Field[str](str, required=True)
57 changes: 57 additions & 0 deletions smib/slack/plugins/space/smibhid/tests/stub_sensor_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import json
import time
from datetime import datetime, timezone

import requests


def main():
utc_time = datetime.now(timezone.utc)
utc_timestamp = int(utc_time.timestamp())
data = [
{
"human_timestamp": utc_time.isoformat(),
"data": {
"SCD30": {
"relative_humidity": 0,
"temperature": 0,
"co2": 0
},
"BME280": {
"pressure": 1019.3,
"humidity": 48.7,
"temperature": 20.03
}
},
"timestamp": utc_timestamp
},
{
"timestamp": utc_timestamp,
"data": {
"SCD30": {
"co2": 1548.1,
"temperature": 26.3,
"relative_humidity": 52.9
},
"BME280": {
"pressure": 632,
"humidity": 57.64,
"temperature": 23.05
}
},
"human_timestamp": utc_time.isoformat()
}
]
headers = {"Content-Type": "application/json", 'device-hostname': "smibhid-dummy"}
url = f"http://localhost/smib/event/smibhid_sensor_log"
print(f"url: {url}")
print(f"headers: {headers}")
print(f"data: {data}")
print(f"JSON data: {json.dumps(data)}")
response = requests.post(url, headers=headers, data=json.dumps(data), verify=False)

print(response.status_code)


if __name__ == '__main__':
main()