<feed xmlns='http://www.w3.org/2005/Atom'>
<title>Odoo/addons/hw_drivers, branch 14.0</title>
<subtitle>The current checkout of upstream Odoo</subtitle>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/'/>
<entry>
<title>[IMP] hw_drivers: Document pitfalls of update_iot_devices logic</title>
<updated>2021-05-10T14:11:59+00:00</updated>
<author>
<name>Raf Geens</name>
<email>raf@odoo.com</email>
</author>
<published>2021-05-05T11:10:18+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=8c584aa86518565a652daf71e3d1824af1fb867a'/>
<id>8c584aa86518565a652daf71e3d1824af1fb867a</id>
<content type='text'>
closes odoo/odoo#70079

Related: odoo/enterprise#18034
Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
closes odoo/odoo#70079

Related: odoo/enterprise#18034
Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] hw_drivers: InterfaceMetaClass violates CPython constraints and breaks import</title>
<updated>2021-05-10T14:11:59+00:00</updated>
<author>
<name>Raf Geens</name>
<email>raf@odoo.com</email>
</author>
<published>2021-04-30T13:37:11+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=edffdd10f3ceb3826bf8897f93fa8290d7fce1ec'/>
<id>edffdd10f3ceb3826bf8897f93fa8290d7fce1ec</id>
<content type='text'>
Currently, none of the classes derived from Interface use `super`. If
it's added, for example by adding this to `SocketInterface`:

```
def __init__(self):
    super().__init__()
```

, a deprecation warning will appear in Python 3.6 and 3.7:

```
2021-04-30 13:14:25,000 24736 WARNING ? py.warnings: /home/pi/odoo/addons/hw_drivers/iot_handlers/interfaces/SocketInterface.py:11: DeprecationWarning: class not set defining 'SocketInterface' as &lt;class 'SocketInterface.py.SocketInterface'&gt;. Was classcell propagated to type.new?
  class SocketInterface(Interface):
```

In Python 3.8 this is no longer a warning and becomes a `RuntimeError`.

The reason this happens is that `InterfaceMetaClass` caches the results
of the `__new__` calls it does in `interfaces`. CPython's data model
specifies that when calling `__new__`, the cell for `__class__` needs to
be passed along to the parent class: https://docs.python.org/3/reference/datamodel.html#creating-the-class-object .

See https://docs.python.org/3/c-api/cell.html for a definition of what
a cell is.

Because of the caching, this doesn't happen when `__new__` is called
multiple times for the same class. In the case of the `SocketInterface`
example, `__new__` is called twice: first when it's imported directly by
`load_iot_handlers` (https://github.com/odoo/odoo/blob/841c016913a87133bf7257c62ae5f6bf7d99e06d/addons/hw_drivers/main.py#L81)
and second when `IngenicoDriver` imports it. The `__class__` cell is
different each time in that case. With the caching present, this means
the second cell isn't propagated correctly, resulting in the warning /
error.

After `load_iot_handlers` has finished, the `Manager`'s `run` method
iterates over `interfaces`, instantiating and starting the loaded
classes. Because of this, simply removing the caching appears to be
sufficient to avoid the issue while keeping the end result the same.

This issue was encountered while forward-porting a V13 PR, which adds a
`super` use to `SocketInterface`. The issue didn't occur in V13, because
the metaclass doesn't have a cache there.

I found a second problem resulting from the caching. I had noticed that
the `socket_devices` dict the `IngenicoDriver` had access to did not
have the same contents as the one the `SocketInterface` was operating
on. This means that whenever you called the `disconnect` function on the
`IngenicoDriver`, which deletes its entry from `socket_devices`, it will
always fail. The bluetooth driver seems to be impacted by the same.

It turns out the reason for that is how downloaded modules get loaded in
`load_iot_handlers`. That logic (using `exec_module`) doesn't actually
import the module, it just executes the code (registering the interfaces
and drivers as a side-effect). This means the module doesn't get cached
in sys.modules. That means that when another module (`IngenicoDriver`)
imports that same module (`SocketInterface`), Python will execute the
entire contents again, in this case effectively replacing socket_devices
with a new dict, which `IngenicoDriver` gets a reference to, while the
`SocketInterface` thread that runs is still using the old reference to
the original dict. Meaning the two are out of sync. See
https://docs.python.org/3/reference/import.html#the-module-cache for
details on how the import caching works.

The reason the classes get out of sync is because the metaclass doesn't
update interfaces when the second actual import happens, so the
`SocketInterface` class that gets instantiated holds a reference to the
old `socket_devices` dict. Removing the caching removes that problem as
well. If there's no caching, both the `SocketInterface` class and
`IngenicoDriver` will hold a reference to the same instance of
`socket_devices`.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently, none of the classes derived from Interface use `super`. If
it's added, for example by adding this to `SocketInterface`:

```
def __init__(self):
    super().__init__()
```

, a deprecation warning will appear in Python 3.6 and 3.7:

```
2021-04-30 13:14:25,000 24736 WARNING ? py.warnings: /home/pi/odoo/addons/hw_drivers/iot_handlers/interfaces/SocketInterface.py:11: DeprecationWarning: class not set defining 'SocketInterface' as &lt;class 'SocketInterface.py.SocketInterface'&gt;. Was classcell propagated to type.new?
  class SocketInterface(Interface):
```

In Python 3.8 this is no longer a warning and becomes a `RuntimeError`.

The reason this happens is that `InterfaceMetaClass` caches the results
of the `__new__` calls it does in `interfaces`. CPython's data model
specifies that when calling `__new__`, the cell for `__class__` needs to
be passed along to the parent class: https://docs.python.org/3/reference/datamodel.html#creating-the-class-object .

See https://docs.python.org/3/c-api/cell.html for a definition of what
a cell is.

Because of the caching, this doesn't happen when `__new__` is called
multiple times for the same class. In the case of the `SocketInterface`
example, `__new__` is called twice: first when it's imported directly by
`load_iot_handlers` (https://github.com/odoo/odoo/blob/841c016913a87133bf7257c62ae5f6bf7d99e06d/addons/hw_drivers/main.py#L81)
and second when `IngenicoDriver` imports it. The `__class__` cell is
different each time in that case. With the caching present, this means
the second cell isn't propagated correctly, resulting in the warning /
error.

After `load_iot_handlers` has finished, the `Manager`'s `run` method
iterates over `interfaces`, instantiating and starting the loaded
classes. Because of this, simply removing the caching appears to be
sufficient to avoid the issue while keeping the end result the same.

This issue was encountered while forward-porting a V13 PR, which adds a
`super` use to `SocketInterface`. The issue didn't occur in V13, because
the metaclass doesn't have a cache there.

I found a second problem resulting from the caching. I had noticed that
the `socket_devices` dict the `IngenicoDriver` had access to did not
have the same contents as the one the `SocketInterface` was operating
on. This means that whenever you called the `disconnect` function on the
`IngenicoDriver`, which deletes its entry from `socket_devices`, it will
always fail. The bluetooth driver seems to be impacted by the same.

It turns out the reason for that is how downloaded modules get loaded in
`load_iot_handlers`. That logic (using `exec_module`) doesn't actually
import the module, it just executes the code (registering the interfaces
and drivers as a side-effect). This means the module doesn't get cached
in sys.modules. That means that when another module (`IngenicoDriver`)
imports that same module (`SocketInterface`), Python will execute the
entire contents again, in this case effectively replacing socket_devices
with a new dict, which `IngenicoDriver` gets a reference to, while the
`SocketInterface` thread that runs is still using the old reference to
the original dict. Meaning the two are out of sync. See
https://docs.python.org/3/reference/import.html#the-module-cache for
details on how the import caching works.

The reason the classes get out of sync is because the metaclass doesn't
update interfaces when the second actual import happens, so the
`SocketInterface` class that gets instantiated holds a reference to the
old `socket_devices` dict. Removing the caching removes that problem as
well. If there's no caching, both the `SocketInterface` class and
`IngenicoDriver` will hold a reference to the same instance of
`socket_devices`.</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] hw_drivers: Start iot_devices thread after registering it</title>
<updated>2021-05-10T14:11:58+00:00</updated>
<author>
<name>Raf Geens</name>
<email>raf@odoo.com</email>
</author>
<published>2021-05-04T12:20:33+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=6c24d30c3910e67ed751327d1554e2e8cf5e958b'/>
<id>6c24d30c3910e67ed751327d1554e2e8cf5e958b</id>
<content type='text'>
This commit was originally part of a larger commit related to an
Ingenico double connection deadlock bugfix in V13, but in V14 most of
the related code has moved to enterprise. When a driver thread is
running, calling `disconnect` on it will delete it from iot_devices. If
the driver thread gets added to iot_devices in the Interface thread
after starting it, this means there is a tiny window of time where
`disconnect` could be called and the thread wouldn't be in iot_devices
yet, resulting in an exception. This change puts the driver thread in
iot_devices before starting it, avoiding that scenario and the need to
check in `disconnect` for that happening.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This commit was originally part of a larger commit related to an
Ingenico double connection deadlock bugfix in V13, but in V14 most of
the related code has moved to enterprise. When a driver thread is
running, calling `disconnect` on it will delete it from iot_devices. If
the driver thread gets added to iot_devices in the Interface thread
after starting it, this means there is a tiny window of time where
`disconnect` could be called and the thread wouldn't be in iot_devices
yet, resulting in an exception. This change puts the driver thread in
iot_devices before starting it, avoiding that scenario and the need to
check in `disconnect` for that happening.</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] hw_drivers: Traceback in 'device_changed'</title>
<updated>2021-02-25T08:37:26+00:00</updated>
<author>
<name>Antoine Prieels</name>
<email>anp@odoo.com</email>
</author>
<published>2021-02-25T08:37:26+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=0850814dda9802973e48ef89d6a81d61fc36a646'/>
<id>0850814dda9802973e48ef89d6a81d61fc36a646</id>
<content type='text'>
Only the 'action' requests have the 'data' parameter set, so any other
request triggering a 'device_changed' failed.

closes odoo/odoo#66792

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Only the 'action' requests have the 'data' parameter set, so any other
request triggering a 'device_changed' failed.

closes odoo/odoo#66792

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[IMP] hw_drivers: Add action data in IoT events</title>
<updated>2020-11-16T14:20:18+00:00</updated>
<author>
<name>Antoine Prieels</name>
<email>anp@odoo.com</email>
</author>
<published>2020-11-06T12:51:00+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=a8c56602ba8301b6e901be7ffeaa219d77401f79'/>
<id>a8c56602ba8301b6e901be7ffeaa219d77401f79</id>
<content type='text'>
Add all the request data in events triggered by IoT actions.

closes odoo/odoo#61420

Taskid: 2320958
Related: odoo/enterprise#14612
Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Add all the request data in events triggered by IoT actions.

closes odoo/odoo#61420

Taskid: 2320958
Related: odoo/enterprise#14612
Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] hw_drivers: Lost IoT events</title>
<updated>2020-11-06T07:11:48+00:00</updated>
<author>
<name>Antoine Prieels</name>
<email>anp@odoo.com</email>
</author>
<published>2020-11-05T14:00:41+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=e3260712ce96a8d81bf807574c334d92c37c6ae4'/>
<id>e3260712ce96a8d81bf807574c334d92c37c6ae4</id>
<content type='text'>
Events coming from the IoT Box were lost in two cases:

1. Create a listener for device 1
2. Send an action to device 1
--&gt; If the action arrives before the listener the event is never sent
to the DB

1. Setup up two listeners for devices 1 &amp; 2
2. After a few seconds, send two consecutive actions to devices 1 &amp; 2
--&gt; Everytime a longpolling request arrives, a new threading.Event
object is created. The first action sets the event, then, before the
new longpolling request arrives, the second action sets the same event,
which is overwritten once the new longpolling request arrives.

We now maintain a list of events, and when a longpolling request
arrives on the IoT Box, we make sure that all events that occured in
the last 5 seconds were received by the DB. If no events were pending,
we wait 50 seconds to check if a new one pops up.

TaskID: 2320958</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Events coming from the IoT Box were lost in two cases:

1. Create a listener for device 1
2. Send an action to device 1
--&gt; If the action arrives before the listener the event is never sent
to the DB

1. Setup up two listeners for devices 1 &amp; 2
2. After a few seconds, send two consecutive actions to devices 1 &amp; 2
--&gt; Everytime a longpolling request arrives, a new threading.Event
object is created. The first action sets the event, then, before the
new longpolling request arrives, the second action sets the same event,
which is overwritten once the new longpolling request arrives.

We now maintain a list of events, and when a longpolling request
arrives on the IoT Box, we make sure that all events that occured in
the last 5 seconds were received by the DB. If no events were pending,
we wait 50 seconds to check if a new one pops up.

TaskID: 2320958</pre>
</div>
</content>
</entry>
<entry>
<title>[IMP] hw_drivers: Support for Star receipt printers</title>
<updated>2020-10-20T11:28:37+00:00</updated>
<author>
<name>Antoine Prieels</name>
<email>anp@odoo.com</email>
</author>
<published>2020-10-19T09:32:19+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=cd0545b98fc1e7a66dd46eb6a283736ef58ac4ff'/>
<id>cd0545b98fc1e7a66dd46eb6a283736ef58ac4ff</id>
<content type='text'>
Add support for Star Line Mode protocol, used by most Star receipt
printers.

closes odoo/odoo#60365

Taskid: 2365648
X-original-commit: 2cf0df13394e0b468afa348c6b1913f35239be5b
Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Add support for Star Line Mode protocol, used by most Star receipt
printers.

closes odoo/odoo#60365

Taskid: 2365648
X-original-commit: 2cf0df13394e0b468afa348c6b1913f35239be5b
Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[IMP] hw_drivers: Remove http.py.iotpatch</title>
<updated>2020-10-19T13:42:10+00:00</updated>
<author>
<name>Antoine Prieels</name>
<email>anp@odoo.com</email>
</author>
<published>2020-10-13T12:55:09+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=a6012f03ff02f04a3d128e33326f932fd22f0ced'/>
<id>a6012f03ff02f04a3d128e33326f932fd22f0ced</id>
<content type='text'>
We used to patch http.py using a diff. This was really not practical
because every time the file was modified, the diff had to be recreated.
We now override the specific methods directly.

closes odoo/odoo#59855

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We used to patch http.py using a diff. This was really not practical
because every time the file was modified, the diff had to be recreated.
We now override the specific methods directly.

closes odoo/odoo#59855

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] hw_drivers: Don't crash if remount fails</title>
<updated>2020-10-07T12:59:32+00:00</updated>
<author>
<name>Antoine Prieels</name>
<email>anp@odoo.com</email>
</author>
<published>2020-10-07T12:59:32+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=5f9874da0f5f5b27c546cd248d08299f0e65544b'/>
<id>5f9874da0f5f5b27c546cd248d08299f0e65544b</id>
<content type='text'>
We sometimes encountered IoT Boxes crashing because the remount failed.
As this isn't a big issue, we won't check the return value of the call
to `mount`.

closes odoo/odoo#59416

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We sometimes encountered IoT Boxes crashing because the remount failed.
As this isn't a big issue, we won't check the return value of the call
to `mount`.

closes odoo/odoo#59416

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] point_of_sale: Fix path to nightly in IoT</title>
<updated>2020-09-17T09:41:13+00:00</updated>
<author>
<name>lejeune quentin</name>
<email>qle@odoo.com</email>
</author>
<published>2020-09-17T09:41:05+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=9512a23f48176fe0e7970039c824281c4af18162'/>
<id>9512a23f48176fe0e7970039c824281c4af18162</id>
<content type='text'>
The path to folder of images of IoT has change.

So we adapt the path for the upgrade of IoT

closes odoo/odoo#57935

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The path to folder of images of IoT has change.

So we adapt the path for the upgrade of IoT

closes odoo/odoo#57935

Signed-off-by: Quentin Lejeune (qle) &lt;qle@odoo.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
