Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #7

Open
wants to merge 3 commits into
base: prod
Choose a base branch
from
Open
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
87 changes: 87 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
====================
Oot - Odoo of things
====================

The main goal of this package is to provide the necessary tools to configure a device
that will send information to odoo.

Device
------

A device is a processing unit that capable to send information to odoo.
All devices must be registered on odoo.
In order to send the data, it will use and HTTP Protocol.

Create your first device
------------------------

Oot class
~~~~~~~~~

First we define a class for the Oot to manage it configuration.
For example:

.. code-block:: python

from oot import OotAmqp, api, Field
from oot.device import CardReader
import time


class DemoOot(OotAmqp):
"""We are using AMQP as it allows to define some extra configuration"""
template = "demo_template"
# Template to be used on odoo
oot_input = "demo_input"
# Input to be used on odoo

# Now we define the configuration fields
admin_id = Field(name="Admin key", required=True)
reader = CardReader(spd=10000)

@api.oot
def get_data_mfrc522(self, **kwargs):
"""We will return the card if a card is readed. Otherwise, we will wait"""
time.sleep(5.0)
while True:
uid = self.reader.scan_card()
if uid:
return uid

Launcher
~~~~~~~~

The second part will be defining a launcher.
The launcher is usually a folder that will contain:

* main file to execute
* a config for the logging
* a `log` folder that will store logs
* a `data` folder that will contain the configuration file

We will try to make an example:

.. code-block:: python

import os
import logging.config
from ootdemo import DemoOot

path = os.path.dirname(os.path.realpath(__file__))

log_folder = path + "/log"

if not os.path.isdir(log_folder):
os.mkdir(log_folder)

logging.config.fileConfig(path + "/ras.logging.conf")

data_folder = path + "/data"

if not os.path.isdir(data_folder):
os.mkdir(data_folder)

DemoOot(data_folder + "/data.json").run()


The example provided on this file will only work on a Raspberry PI with an MFRC522.
19 changes: 19 additions & 0 deletions demo/file_reader/launcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
import logging.config
from ootdemo import DemoOot

path = os.path.dirname(os.path.realpath(__file__))

log_folder = path + "/log"

if not os.path.isdir(log_folder):
os.mkdir(log_folder)

logging.config.fileConfig(path + "/logging.conf")

data_folder = path + "/data"

if not os.path.isdir(data_folder):
os.mkdir(data_folder)

DemoOot(data_folder + "/data.json", data_folder + "/read").run()
35 changes: 35 additions & 0 deletions demo/file_reader/logging.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[loggers]
keys=root,oot,ootdemo

[handlers]
keys=consoleHandler

[formatters]
keys=consoleFormatter

[logger_root]
level=INFO
handlers=consoleHandler

[logger_oot]
level=DEBUG
handlers=consoleHandler
qualname=oot
propagate=0

[logger_ootdemo]
level=DEBUG
handlers=consoleHandler
qualname=ootdemo
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=consoleFormatter
args=(sys.stdout,)

[formatter_consoleFormatter]
format=%(levelname)s: %(message)s
datefmt=

1 change: 1 addition & 0 deletions demo/file_reader/ootdemo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .ootdemo import DemoOot
55 changes: 55 additions & 0 deletions demo/file_reader/ootdemo/ootdemo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from oot import OotAmqp, api, Field
import os
import logging
import time

_logger = logging.getLogger(__name__)


class FileReader:
def __init__(self, file_path, delay=15):
self.file_path = file_path
self.delay = delay

def scan(self):
while True:
if not os.path.exists(self.file_path):
time.sleep(0.1)
continue
if os.path.getmtime(self.file_path) > time.time() - self.delay:
time.sleep(0.1)
continue
with open(self.file_path, "r") as f:
data = f.read()
os.remove(self.file_path)
return data


class DemoOot(OotAmqp):
"""We are using AMQP as it allows to define some extra configuration"""
template = "demo_template"
# Template to be used on odoo
oot_input = "demo_input"
_ignore_access_point = True
# Input to be used on odoo

# Now we define the configuration fields
admin_id = Field(name="Admin key", required=True)

def __init__(self, connection, file_path):
super(DemoOot, self).__init__(connection)
self.reader = FileReader(file_path)

@api.oot
def get_data_mfrc522(self, **kwargs):
"""We will return the card if a card is readed. Otherwise, we will wait"""
time.sleep(5.0)
while True:
uid = self.reader.scan()
if uid:
_logger.info("Sending %s" % uid)
return uid

def process_result(self, key, result, **kwargs):
_logger.info("For %s, we received the following result: %s" % (key, result))
return super(DemoOot, self).process_result(key, result, **kwargs)
3 changes: 2 additions & 1 deletion oot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
from .oot import Oot
from .oot_multiprocess import OotMultiProcessing
from .oot_amqp import OotAmqp
from . import device
from . import upgrade
from . import api
from .fields import Field
17 changes: 17 additions & 0 deletions oot/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
def attrsettermethod(method, attr, value):
return setattr(method, attr, value) or method


def attrsetter(attr, value):
""" Return a function that sets ``attr`` on its argument and returns it. """
return lambda method: attrsettermethod(method, attr, value)


def oot(method):
"""Marks the method as a process that will send data to Odoo"""
return attrsettermethod(method, "_oot_process", True)


def amqp(command):
"""Marks the method as and amqp command"""
return attrsetter("_amqp_command", command)
4 changes: 3 additions & 1 deletion oot/connection/consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ def run(self):
channel.basic_qos(prefetch_count=1)
channel.queue_declare(self.queue, **self.queue_options)
channel.exchange_declare(
exchange=self.exchange_name, exchange_type=self.exchange_type, passive=True,
exchange=self.exchange_name,
exchange_type=self.exchange_type,
passive=True,
)
for routing_key in self.options:
channel.queue_bind(
Expand Down
18 changes: 18 additions & 0 deletions oot/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Field:
"""This class is intended to be used to define fields for the configuration
"""
def __init__(self, name, description=False, placeholder=False, required=True):
self.name = name
self.description = description
self.placeholder = placeholder
self.required = required

def generate(self):
result = {"name": self.name}
if self.description:
result["description"] = self.description
if self.placeholder:
result["placeHolder"] = self.placeholder
if self.required:
result["required"] = self.required
return result
Loading