Skip to content

Commit

Permalink
added models and starte refactoring iot_agent
Browse files Browse the repository at this point in the history
  • Loading branch information
tstorek committed Feb 19, 2021
1 parent cb59438 commit fdcdc9d
Show file tree
Hide file tree
Showing 16 changed files with 306 additions and 25 deletions.
2 changes: 1 addition & 1 deletion filip/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__version__ = '0.1'
__all__ = ["ocb", "iota", "timeseries", "utils", "testing",
__all__ = ["ocb", "iota", "timeseries", "utils", "tests",
"config", "client"]


Expand Down
2 changes: 2 additions & 0 deletions filip/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .settings import settings
from .models import FiwareHeader
20 changes: 20 additions & 0 deletions filip/core/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from aenum import Enum
from pydantic import BaseModel, Field, validator

class DataType(str, Enum):
"""
Expand Down Expand Up @@ -26,3 +27,22 @@ class DataType(str, Enum):
Time = "Time", "A point in time recurring on multiple days in the form " \
"hh:mm:ss[Z|(+|-)hh:mm] (see XML schema for details)."

class FiwareHeader(BaseModel):
service: str = Field(
alias="Fiware-Service",
default="",
max_length=50,
description="Fiware service used for multitancy"
)
path: str = Field(
alias="Fiware-ServicePath",
default="/",
description="Fiware service path",
max_length = 51,
)

@validator('path')
def validate_service_path(cls, v):
assert v.startswith('/'), \
"Service path must have a trailing slash ('/')"
return v
17 changes: 17 additions & 0 deletions filip/core/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pydantic import BaseSettings, Field, AnyHttpUrl

class _Settings(BaseSettings):
OCB_URL: AnyHttpUrl = Field(default="http://localhost:1026",
env=['ORION_URL', 'OCB_URL'])
IOTA_URL: AnyHttpUrl = Field(default="http://localhost:4041",
env='IOTA_URL')
QL_URL: AnyHttpUrl = Field(default="http://localhost:8668",
env=['QUANTUMLEAP_URL', 'QL_URL'])

class Config:
env_file = '../../.env'
env_file_encoding = 'utf-8'
case_sensitive = False


settings = _Settings()
File renamed without changes.
1 change: 1 addition & 0 deletions filip/iota/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from .agent import Agent
from .device import Device
from .device_group import DeviceGroup
from .iota_client import IoTAClient
11 changes: 3 additions & 8 deletions filip/iota/agent.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import requests
import datetime
import json
import logging

from filip.utils import request_utils as requtils
from filip.testing import test
from core import test
from filip.iota.device_group import DeviceGroup
from filip.iota.device import Device
from filip.config import Config

import logging

log = logging.getLogger('iot')


PROTOCOLS = ['IoTA-JSON', 'IoTA-UL']


Expand Down Expand Up @@ -201,11 +198,9 @@ def update_device(self, device_group: DeviceGroup, device: Device, payload: dict
data=payload,
headers=headers)



ok, retstr = requtils.response_ok(response)
if not ok:
level, retstr = requtils.logging_switch(response)
self.log_switch(level, retstr)
else:
log.info(f"Device {device.device_id} successfully updated!")
log.info(f"Device {device.device_id} successfully updated!")
103 changes: 103 additions & 0 deletions filip/iota/iota_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import requests
import logging
import json
from typing import List, Union
from urllib.parse import urljoin
from core import settings, FiwareHeader
from .models import Device, Protocol

logger = logging.getLogger(__name__)


class IoTAClient():
def __init__(self, fiware_header: FiwareHeader = None):
self.headers = dict()
if not fiware_header:
fiware_header = FiwareHeader()
self.headers.update(fiware_header.dict(by_alias=True))

def get_version(self):
url = urljoin(settings.IOTA_URL, 'version')
url = 'http://github.com/'
try:
res = requests.get(url=url, headers=self.headers)
res.raise_for_status()
except requests.exceptions.RequestException as e:
logger.error(e)

def get_devices(self, *, limit: int = 20, offset: int = 20,
detailed: bool = None, entity: str = None,
protocol: Protocol = None) -> List[Device]:
"""
Returns a list of all the devices in the device registry with all
its data.
Args:
limit: if present, limits the number of devices returned in the list.
offset: if present, skip that number of devices from the original query.
detailed:
entity:
protocol:
Returns:
"""
url = urljoin(settings.IOTA_URL, 'iot/devices')
headers = self.headers
params = {param for param in locals().items() if param is not None}
try:
res = requests.get(url=url, headers=headers, params=params)
if res.ok:
return [Device(**device) for device in res.json()['devices']]
else:
res.raise_for_status()
except requests.exceptions.RequestException as e:
logger.error(e)

def post_devices(self):
url = urljoin(settings.IOTA_URL, 'version')

def get_device(self, *, device_id) -> Device:
"""
Returns all the information about a particular device.
Args:
device_id:
Returns:
Device
"""
url = urljoin(settings.IOTA_URL, 'iot/devices', device_id)
headers = self.headers
try:
res = requests.get(url=url, headers=headers)
if res.ok:
return Device.parse_raw(res.json())
else:
res.raise_for_status()
except requests.exceptions.RequestException as e:
logger.error(e)

def update_device(self, *, device_id):
pass

def delete_device(self, *, device_id) -> None:
"""
Remove a device from the device registry. No payload is required
or received.
Args:
device_id:
Returns:
None
"""
url = urljoin(settings.IOTA_URL, 'iot/devices', device_id)
headers = self.headers
try:
res = requests.delete(url=url, headers=headers)
if res.ok:
logger.info(f"Device {device_id} successfully deleted!")
else:
res.raise_for_status()
except requests.exceptions.RequestException as e:
logger.error(e)
logger.error(f"Device {device_id} was not deleted!")
10 changes: 7 additions & 3 deletions filip/iota/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,15 @@ class Device(BaseModel):
)
service: Optional[str] = Field(
description="Name of the service the device belongs to "
"(will be used in the fiware-service header)."
"(will be used in the fiware-service header).",
max_length=50
)
service_path: Optional[str] = Field(
default="/",
description="Name of the subservice the device belongs to "
"(used in the fiware-servicepath header).")
"(used in the fiware-servicepath header).",
max_length=51
)
entity_name: str = Field(
description="Name of the entity representing the device in "
"the Context Broker"
Expand All @@ -199,6 +202,7 @@ class Device(BaseModel):
description="Type of the entity in the Context Broker"
)
timezone: Optional[str] = Field(
default='Europe/London',
description="Time zone of the sensor if it has any"
)
timestamp: Optional[bool] = Field(
Expand Down Expand Up @@ -275,4 +279,4 @@ def validate_timezone(cls, v):

if __name__ == '__main__':
device = Device(device_id="saf", entity_name="saf", entity_type="all")
print(device.json(indent=2, skip_defaults=True))
print(device.json(indent=2))
6 changes: 3 additions & 3 deletions filip/ocb/orion.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import requests
from filip.utils import request_utils as requtils
from filip.testing import test
from core import test
import math
import logging

Expand Down Expand Up @@ -227,8 +227,8 @@ def test_connection(self):
:return: Boolean, True if the service is reachable, False if not.
"""
boolean = test.test_connection(client=self.session,
url=self.url+'/version',
service_name=__name__)
url=self.url+'/version',
service_name=__name__)
return boolean

def post_entity(self, entity: Entity, force_update: bool = True):
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions filip/tests/test.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
IOTA_URL="http://myHost:4041"
OCB_URL="http://myHost:1026"
QL_URL="http://myHost:8668"
46 changes: 46 additions & 0 deletions filip/tests/test_iota.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import unittest
# Third-party imports...
import requests
from unittest.mock import Mock, patch
from iota import IoTAClient, models

class TestClient(unittest.TestCase):
def setUp(self) -> None:
self.device = {
"device_id": "saf",
"service": None,
"service_path": "/",
"entity_name": "saf",
"entity_type": "all",
"timezone": 'Europe/Berlin',
"timestamp": None,
"apikey": "1234",
"endpoint": None,
"protocol": None,
"transport": None,
"lazy": None,
"commands": None,
"attributes": None,
"static_attributes": None,
"internal_attributes": None,
"expressionLanguage": None,
"explicitAttrs": None,
"ngsiVersion": None
}
self.client = IoTAClient()

def test_device_model(self):
device = models.Device(**self.device)
self.assertEqual(device.dict(), self.device)

def test_get_version(self):
res = self.client.get_version()
if res is not None:
print(type(res.json()))

def test_device_endpoints(self):
self.client.post_devices()

def test_get_device(self):
res = requests.get('http://jsonplaceholder.typicode.com/todos')
self.assertTrue(res.ok)
16 changes: 16 additions & 0 deletions filip/tests/test_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import unittest
from core.settings import _Settings


class TestSettings(unittest.TestCase):
def setUp(self) -> None:
self.settings_parsing = _Settings(_env_file='test.env')
self.settings_dotenv = _Settings(_env_file='../../example.env')

def test_load_dotenv(self):
self.assertEqual(self.settings_parsing.IOTA_URL, "http://myHost:4041")
self.assertEqual(self.settings_parsing.OCB_URL, "http://myHost:1026")
self.assertEqual(self.settings_parsing.QL_URL, "http://myHost:8668")

def test_example_dotenv(self):
self.assertEqual(self.settings_parsing, self.settings_dotenv)
2 changes: 1 addition & 1 deletion filip/timeseries/timeseries.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from ocb import Subscription as sub
from ocb import *
from filip.utils import request_utils as requtils
from filip.testing import test
from core import test
import requests
import json

Expand Down
Loading

0 comments on commit fdcdc9d

Please sign in to comment.