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

[MIG] iot_input_oca: Migration to 16.0 #87

Merged
merged 19 commits into from
Jun 15, 2023
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
154 changes: 154 additions & 0 deletions iot_input_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
=========
IoT Input
=========

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fiot-lightgray.png?logo=github
:target: https://github.com/OCA/iot/tree/15.0/iot_input_oca
:alt: OCA/iot
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/iot-15-0/iot-15-0-iot_input_oca
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/269/15.0
:alt: Try me on Runbot

|badge1| |badge2| |badge3| |badge4| |badge5|

This addon allows to use a device in order to input data to odoo automatically.

It opens a URL that a device can use to connect (with a password) that can only
execute an specific action.

Inputs are useful when a device wants to communicate to odoo for a single
and simple action.
This way, the device does not need to be configured with a odoo user and
password, it is handled by odoo devices.

Examples:

* Sending the temperature every three minutes.
* Sending the RFID that the device has received in order to perform some action

**Table of contents**

.. contents::
:local:

Usage
=====

There are two endpoints you can use:
Endpoint 1: /iot/<serial>/action

Takes `application/x-www-form-urlencoded` parameters:
passphase, value (where value is a JSON object)

1. Create a Device on `IoT > Config Devices`
2. Access the Inputs section of the device
3. Create an input. You must define a serial, passphrase, function and model

The function that the system will call must be of the following kind::

@api.model
def call_function(self, key):
return {}

Where `key` is the input string send by the device and the result must be a dictionary
that will be responded to the device as a JSON.

Endpoint 2: /iot/<device_identification>/multi_input
It can be used to send values with multiple data in one POST request such as:
- Values for inputs of the same device with different address (multi input)
- Values for inputs of the same device with same address, different values (multi event)
- Mix of the above (multi input, multi event)

Takes `application/x-www-form-urlencoded` parameters:
passphase, values (a JSON array of JSON objects)

It is called using device_identification and passing two POST parameters: device passphrase and
a JSON string containing an array of values for input
- The value for the `address` key can be a string or a numeric (to conserve bytes in memory
restricted devices when creating the JSON object) and is converted to string when parsing.
- The value for the `value` key can either be string, number or boolean according to
JSON specs.
You can see an example of a valid JSON input object in the examples folder, using a few
combinations.

It requires the function that the system will call must be of the following kind::

@api.model
def call_function(self, key):
'do something
if err:
return {'status': 'error', 'message': 'The error message you want to send to the device'}
return {'status': 'ok', 'message': 'Optional success message'}

Where `key` is a dict send by the device having at least value for keys: 'address', 'value'

The function must always return a JSON with status and message. If value contains a value
with 'uuid' as key, it is returned along with the object for the IoT device to identify
success/failure per record.

It has full error reporting and the return value is a JSON array of dicts containing at
least status and message. Error message respose is at some points generic, though
extended logging is done in Odoo server logs.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/iot/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/iot/issues/new?body=module:%20iot_input_oca%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* Creu Blanca

Contributors
~~~~~~~~~~~~

* Enric Tobella <etobella@creublanca.es>
* Dimitrios Tanis <dtanis@tanisfood.gr>

Maintainers
~~~~~~~~~~~

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-etobella| image:: https://github.com/etobella.png?size=40px
:target: https://github.com/etobella
:alt: etobella

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-etobella|

This module is part of the `OCA/iot <https://github.com/OCA/iot/tree/15.0/iot_input_oca>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions iot_input_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import controller
19 changes: 19 additions & 0 deletions iot_input_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (C) 2018 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "IoT Input",
"version": "16.0.1.0.0",
"author": "Creu Blanca, Odoo Community Association (OCA)",
"category": "IoT",
"license": "AGPL-3",
"installable": True,
"summary": "IoT Input module",
"depends": ["iot_oca"],
"website": "https://github.com/OCA/iot",
"maintainers": ["etobella"],
"data": [
"security/ir.model.access.csv",
"views/iot_device_views.xml",
"views/iot_device_input_views.xml",
],
}
1 change: 1 addition & 0 deletions iot_input_oca/controller/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import iot_input_controller
105 changes: 105 additions & 0 deletions iot_input_oca/controller/iot_input_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Copyright 2018 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import json
import logging

from odoo import _, http

_logger = logging.getLogger(__name__)


class CallIot(http.Controller):
@http.route(
["/iot/<serial>/action"],
type="http",
auth="none",
methods=["POST"],
csrf=False,
)
def call_unauthorized_iot(self, serial, passphrase=False, *args, **kwargs):
request = http.request
if not request.env:
return json.dumps(False)

Check warning on line 23 in iot_input_oca/controller/iot_input_controller.py

View check run for this annotation

Codecov / codecov/patch

iot_input_oca/controller/iot_input_controller.py#L23

Added line #L23 was not covered by tests
return json.dumps(
request.env["iot.device.input"]
.sudo()
.get_device(serial, passphrase)
.call_device(**kwargs)
)

@http.route(
["/iot/<serial>/multi_input"],
type="http",
auth="none",
methods=["POST"],
csrf=False,
)
def call_unauthorized_iot_multi_input(
self, serial, passphrase=False, values=False, *args, **kwargs
):
"""Controller to write multiple input data to device inputs
:param string passphrase:
Device passphrase in POST data.
:param string values:
JSON formatted string containing a JSON an array of JSON objects.
"""
request = http.request
if not request.env:
_logger.warning("env not set")
return json.dumps({"status": "error", "message": _("Server Error")})

Check warning on line 52 in iot_input_oca/controller/iot_input_controller.py

View check run for this annotation

Codecov / codecov/patch

iot_input_oca/controller/iot_input_controller.py#L51-L52

Added lines #L51 - L52 were not covered by tests
if not passphrase:
_logger.warning("Passphrase is required")
return json.dumps(
{"status": "error", "message": _("Passphrase is required")}
)
if not values:
_logger.warning("Values is required")
return json.dumps({"status": "error", "message": _("Values is required")})
# Decode JSON object here and use pure python objects in further calls
try:
if isinstance(values, str):
values = json.loads(values)
if not isinstance(values, list):
raise SyntaxError
except json.decoder.JSONDecodeError:
_logger.warning("Values is not a valid JSON")
return json.dumps(
{"status": "error", "message": _("Values is not a valid JSON")}
)
except SyntaxError:
_logger.warning("Values should be a JSON array of JSON objects")
return json.dumps(
{
"status": "error",
"message": _("Values should be a JSON array of JSON objects"),
}
)
# Encode response to JSON and return
result = (
request.env["iot.device.input"]
.sudo()
.get_device(serial, passphrase)
.call_device(values=values)
)
if result["status"] != "ok":
return json.dumps({"status": result["status"]})
return json.dumps(result["result"])

@http.route(
["/iot/<serial>/check"], type="http", auth="none", methods=["POST"], csrf=False
)
def check_unauthorized_iot(self, serial, *args, **kwargs):
request = http.request
if not request.env:
return json.dumps(False)

Check warning on line 97 in iot_input_oca/controller/iot_input_controller.py

View check run for this annotation

Codecov / codecov/patch

iot_input_oca/controller/iot_input_controller.py#L97

Added line #L97 was not covered by tests
device = (
request.env["iot.device.input"]
.sudo()
.get_device(serial, kwargs["passphrase"])
)
if device:
return json.dumps({"state": True})
return json.dumps({"state": False})
19 changes: 19 additions & 0 deletions iot_input_oca/examples/multi_input_values.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[
{
"address": "ZMPT101B_1",
"value": 230
},
{
"address": 1,
"value": true
},
{
"address": 2,
"value": "Door opened",
"uuid": "abcde"
},
{
"address": 10,
"value": -18.5
}
]
Loading
Loading