Initial commit: Hw packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:52 +02:00
commit a9d00500da
161 changed files with 10506 additions and 0 deletions

View file

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from re import sub, finditer
import subprocess
import RPi.GPIO as GPIO
import logging
from odoo.addons.hw_drivers.interface import Interface
_logger = logging.getLogger(__name__)
try:
from vcgencmd import Vcgencmd
except ImportError:
Vcgencmd = None
_logger.warning('Could not import library vcgencmd')
class DisplayInterface(Interface):
_loop_delay = 0
connection_type = 'display'
def get_devices(self):
# If no display connected, create "fake" device to be accessed from another computer
display_devices = {
'distant_display' : {
'name': "Distant Display",
},
}
if Vcgencmd:
return self.get_devices_vcgencmd() or display_devices
else:
return self.get_devices_tvservice() or display_devices
def get_devices_tvservice(self):
display_devices = {}
displays = subprocess.check_output(['tvservice', '-l']).decode()
x_screen = 0
for match in finditer(r'Display Number (\d), type HDMI (\d)', displays):
display_id, hdmi_id = match.groups()
tvservice_output = subprocess.check_output(['tvservice', '-nv', display_id]).decode().strip()
if tvservice_output:
display_name = tvservice_output.split('=')[1]
display_identifier = sub('[^a-zA-Z0-9 ]+', '', display_name).replace(' ', '_') + "_" + str(hdmi_id)
iot_device = {
'identifier': display_identifier,
'name': display_name,
'x_screen': str(x_screen),
}
display_devices[display_identifier] = iot_device
x_screen += 1
return display_devices
def get_devices_vcgencmd(self):
"""
With the new IoT build 23_11 which uses Raspi OS Bookworm,
tvservice is no longer usable.
vcgencmd returns the display power state as on or off of the display whose ID is passed as the parameter.
The display ID for the preceding three methods are determined by the following table.
Display ID
Main LCD 0
Secondary LCD 1
HDMI 0 2
Composite 3
HDMI 1 7
"""
display_devices = {}
x_screen = 0
hdmi_port = {'hdmi_0' : 2} # HDMI 0
rpi_type = GPIO.RPI_INFO.get('TYPE')
# Check if it is a RPI 3B+ beacause he response on for booth hdmi port
if 'Pi 4' in rpi_type:
hdmi_port.update({'hdmi_1': 7}) # HDMI 1
try:
for hdmi in hdmi_port:
power_state_hdmi = Vcgencmd().display_power_state(hdmi_port.get(hdmi))
if power_state_hdmi == 'on':
iot_device = {
'identifier': hdmi,
'name': 'Display hdmi ' + str(x_screen),
'x_screen': str(x_screen),
}
display_devices[hdmi] = iot_device
x_screen += 1
except subprocess.CalledProcessError:
_logger.warning('Vcgencmd "display_power_state" method call failed')
return display_devices

View file

@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from cups import Connection as cups_connection
from re import sub
from threading import Lock
from odoo.addons.hw_drivers.interface import Interface
conn = cups_connection()
PPDs = conn.getPPDs()
cups_lock = Lock() # We can only make one call to Cups at a time
class PrinterInterface(Interface):
_loop_delay = 120
connection_type = 'printer'
printer_devices = {}
def get_devices(self):
discovered_devices = {}
with cups_lock:
printers = conn.getPrinters()
devices = conn.getDevices()
for printer_name, printer in printers.items():
path = printer.get('device-uri', False)
if printer_name != self.get_identifier(path):
printer.update({'supported': True}) # these printers are automatically supported
device_class = 'network'
if 'usb' in printer.get('device-uri'):
device_class = 'direct'
printer.update({'device-class': device_class})
printer.update({'device-make-and-model': printer_name}) # give name setted in Cups
printer.update({'device-id': ''})
devices.update({printer_name: printer})
for path, device in devices.items():
identifier = self.get_identifier(path)
device.update({'identifier': identifier})
device.update({'url': path})
device.update({'disconnect_counter': 0})
discovered_devices.update({identifier: device})
self.printer_devices.update(discovered_devices)
# Deal with devices which are on the list but were not found during this call of "get_devices"
# If they aren't detected 3 times consecutively, remove them from the list of available devices
for device in list(self.printer_devices):
if not discovered_devices.get(device):
disconnect_counter = self.printer_devices.get(device).get('disconnect_counter')
if disconnect_counter >= 2:
self.printer_devices.pop(device, None)
else:
self.printer_devices[device].update({'disconnect_counter': disconnect_counter + 1})
return dict(self.printer_devices)
def get_identifier(self, path):
"""
Necessary because the path is not always a valid Cups identifier,
as it may contain characters typically found in URLs or paths.
- Removes characters: ':', '/', '.', '\', and space.
- Removes the exact strings: "uuid=" and "serial=".
Example 1:
Input: "ipp://printers/printer1:1234/abcd"
Output: "ippprintersprinter11234abcd"
Example 2:
Input: "uuid=1234-5678-90ab-cdef"
Output: "1234-5678-90ab-cdef
"""
return sub(r'[:\/\.\\ ]|(uuid=)|(serial=)', '', path)

View file

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import win32print
from odoo.addons.hw_drivers.interface import Interface
class PrinterInterface(Interface):
_loop_delay = 30
connection_type = 'printer'
def get_devices(self):
printer_devices = {}
printers = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL)
for printer in printers:
identifier = printer[2]
handle_printer = win32print.OpenPrinter(identifier)
win32print.GetPrinter(handle_printer, 2)
printer_devices[identifier] = {
'identifier': identifier,
'printer_handle': handle_printer,
}
return printer_devices

View file

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import serial.tools.list_ports
from odoo.addons.hw_drivers.interface import Interface
class SerialInterface(Interface):
connection_type = 'serial'
def get_devices(self):
serial_devices = {}
for port in serial.tools.list_ports.comports():
serial_devices[port.device] = {
'identifier': port.device
}
return serial_devices

View file

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from usb import core
from odoo.addons.hw_drivers.interface import Interface
class USBInterface(Interface):
connection_type = 'usb'
def get_devices(self):
"""
USB devices are identified by a combination of their `idVendor` and
`idProduct`. We can't be sure this combination in unique per equipment.
To still allow connecting multiple similar equipments, we complete the
identifier by a counter. The drawbacks are we can't be sure the equipments
will get the same identifiers after a reboot or a disconnect/reconnect.
"""
usb_devices = {}
devs = core.find(find_all=True)
cpt = 2
for dev in devs:
identifier = "usb_%04x:%04x" % (dev.idVendor, dev.idProduct)
if identifier in usb_devices:
identifier += '_%s' % cpt
cpt += 1
usb_devices[identifier] = dev
return usb_devices