From 7279223f06fd8fb93c24387706e367e437009366 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 27 Jun 2026 17:17:04 +0100 Subject: [PATCH 01/24] Update CI tasks in test.yml Enable nosetests --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d46f7a1b..b2c04e9e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,8 +7,8 @@ jobs: strategy: fail-fast: false matrix: - task: [data-check, codespell] - #spellintian, nosetests, karma, lint, closure-compiler, + task: [nosetests, data-check, codespell] + #spellintian, karma, lint, closure-compiler, steps: - uses: actions/checkout@master - name: Install dependencies From 9b793c09efd613f2feec01738f081ffeceba5655 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 27 Jun 2026 18:06:56 +0100 Subject: [PATCH 02/24] Update test workflow to install nose conditionally Add conditional installation of 'nose' for nosetests task --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2c04e9e..940e673c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,6 +15,7 @@ jobs: env: TASK: ${{ matrix.task }} run: | + if [ "$TASK" = "nosetests" ]; then pip install nose; fi if [ "$TASK" = "nosetests" -o "$TASK" = "flake8" -o "$TASK" = "flake8-wip" ]; then pip install json-spec; fi if [ "$TASK" = "karma" -o "$TASK" = "lint" -o "$TASK" = "closure-compiler" ]; then npm install -g grunt-cli; fi if [ "$TASK" = "karma" -o "$TASK" = "lint" -o "$TASK" = "closure-compiler" ]; then npm install; fi From 28a7dc5f297f946b4b3bbfe915c427e2e2ab827a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 27 Jun 2026 22:05:24 +0100 Subject: [PATCH 03/24] Switch to pynose for more modern Python --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 940e673c..75dcb5a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: env: TASK: ${{ matrix.task }} run: | - if [ "$TASK" = "nosetests" ]; then pip install nose; fi + if [ "$TASK" = "nosetests" ]; then pip install pynose; fi if [ "$TASK" = "nosetests" -o "$TASK" = "flake8" -o "$TASK" = "flake8-wip" ]; then pip install json-spec; fi if [ "$TASK" = "karma" -o "$TASK" = "lint" -o "$TASK" = "closure-compiler" ]; then npm install -g grunt-cli; fi if [ "$TASK" = "karma" -o "$TASK" = "lint" -o "$TASK" = "closure-compiler" ]; then npm install; fi From 6530b0b1811fcaed96ccd378dfb7fc3b993adb5c Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 27 Jun 2026 22:07:03 +0100 Subject: [PATCH 04/24] Change nosetests dependency to pynose in workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 940e673c..75dcb5a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: env: TASK: ${{ matrix.task }} run: | - if [ "$TASK" = "nosetests" ]; then pip install nose; fi + if [ "$TASK" = "nosetests" ]; then pip install pynose; fi if [ "$TASK" = "nosetests" -o "$TASK" = "flake8" -o "$TASK" = "flake8-wip" ]; then pip install json-spec; fi if [ "$TASK" = "karma" -o "$TASK" = "lint" -o "$TASK" = "closure-compiler" ]; then npm install -g grunt-cli; fi if [ "$TASK" = "karma" -o "$TASK" = "lint" -o "$TASK" = "closure-compiler" ]; then npm install; fi From 2178e1323507602f96b05733c4efe05535bd23fe Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 27 Jun 2026 22:26:40 +0100 Subject: [PATCH 05/24] Python 2 and 3 compatible version of execfile --- data/controller_test.py | 3 ++- data/manufacturer_test.py | 6 ++++-- data/model_test.py | 3 ++- data/node_test.py | 3 ++- data/pid_test.py | 3 ++- data/product_category_test.py | 3 ++- data/sensor_test.py | 3 ++- data/software_test.py | 3 ++- data/splitter_test.py | 3 ++- tools/missing_manufacturer_links.py | 6 ++++-- 10 files changed, 24 insertions(+), 12 deletions(-) diff --git a/data/controller_test.py b/data/controller_test.py index 9eedf6e7..4a071fa8 100644 --- a/data/controller_test.py +++ b/data/controller_test.py @@ -24,7 +24,8 @@ class TestControllerData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/controller_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/controller_data.py").read(), globals, locals) self.data = locals['CONTROLLER_DATA'] def test_ControllerData(self): diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 2076b9a7..1f4ebefe 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -30,11 +30,13 @@ class TestManufacturers(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/manufacturer_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/manufacturer_data.py").read(), globals, locals) self.data = locals['MANUFACTURER_DATA'] globals = {} locals = {} - execfile("data/manufacturer_links.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/manufacturer_links.py").read(), globals, locals) self.links = locals['MANUFACTURER_LINKS'] def test_ManufacturerData(self): diff --git a/data/model_test.py b/data/model_test.py index 67e3213c..b97e148b 100644 --- a/data/model_test.py +++ b/data/model_test.py @@ -24,7 +24,8 @@ class TestDeviceModelData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/model_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/model_data.py").read(), globals, locals) self.data = locals['DEVICE_MODEL_DATA'] def test_DeviceModelData(self): diff --git a/data/node_test.py b/data/node_test.py index f5b1c371..6396cec7 100644 --- a/data/node_test.py +++ b/data/node_test.py @@ -24,7 +24,8 @@ class TestNodeData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/node_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/node_data.py").read(), globals, locals) self.data = locals['NODE_DATA'] def test_NodeData(self): diff --git a/data/pid_test.py b/data/pid_test.py index fd19a87e..b4feca3c 100644 --- a/data/pid_test.py +++ b/data/pid_test.py @@ -301,7 +301,8 @@ class TestPidData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/pid_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/pid_data.py").read(), globals, locals) self.manufacturer_pids = locals['MANUFACTURER_PIDS'] self.esta_pids = locals['ESTA_PIDS'] self.pid_validator = jsonspec.validators.load(PID_VALIDATOR) diff --git a/data/product_category_test.py b/data/product_category_test.py index a64818df..9ef73ac2 100644 --- a/data/product_category_test.py +++ b/data/product_category_test.py @@ -24,7 +24,8 @@ class TestProductCategoryData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/product_categories.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/product_categories.py").read(), globals, locals) self.data = locals['PRODUCT_CATEGORIES'] def test_ProductCategoryData(self): diff --git a/data/sensor_test.py b/data/sensor_test.py index 614c9759..d8e571b0 100644 --- a/data/sensor_test.py +++ b/data/sensor_test.py @@ -24,7 +24,8 @@ class TestSensorTypes(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/sensor_types.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/sensor_types.py").read(), globals, locals) self.data = locals['SENSOR_TYPES'] def test_SensorTypeData(self): diff --git a/data/software_test.py b/data/software_test.py index f8a35adb..f0e38c96 100644 --- a/data/software_test.py +++ b/data/software_test.py @@ -24,7 +24,8 @@ class TestSoftwareData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/software_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/software_data.py").read(), globals, locals) self.data = locals['SOFTWARE_DATA'] def test_SoftwareData(self): diff --git a/data/splitter_test.py b/data/splitter_test.py index 5eb7d372..22858fac 100644 --- a/data/splitter_test.py +++ b/data/splitter_test.py @@ -24,7 +24,8 @@ class TestSplitterData(unittest.TestCase): def setUp(self): globals = {} locals = {} - execfile("data/splitter_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/splitter_data.py").read(), globals, locals) self.data = locals['SPLITTER_DATA'] def test_SplitterData(self): diff --git a/tools/missing_manufacturer_links.py b/tools/missing_manufacturer_links.py index d3e25f1a..284e20e8 100755 --- a/tools/missing_manufacturer_links.py +++ b/tools/missing_manufacturer_links.py @@ -54,11 +54,13 @@ def Footer(): if __name__ == '__main__': globals = {} locals = {} - execfile("data/manufacturer_data.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/manufacturer_data.py").read(), globals, locals) raw_manufacturers = locals['MANUFACTURER_DATA'] globals = {} locals = {} - execfile("data/manufacturer_links.py", globals, locals) + # Python 2 and 3 compatible version of execfile + exec(open("data/manufacturer_links.py").read(), globals, locals) raw_links = locals['MANUFACTURER_LINKS'] manufacturers = {} From cd8b7814f482bc4f7d419d16c282cf4aa1131ec7 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 28 Jun 2026 11:32:38 +0100 Subject: [PATCH 06/24] Python 2 and 3 compatible URL checking --- data/manufacturer_test.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 1f4ebefe..921442eb 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -17,13 +17,32 @@ # Copyright (C) 2015 Simon Newton import unittest -import urllib2 import pprint +import sys from socket import error as SocketError -from urllib2 import HTTPError -from urllib2 import URLError from ssl import SSLError +if sys.version_info >= (3, 0): + try: + from urllib.request import build_opener + from urllib.request import HTTPCookieProcessor + from urllib.request import Request + from urllib.error import HTTPError + from urllib.error import URLError + except ImportError: + import urllib2 + from urllib2 import build_opener + from urllib2 import HTTPCookieProcessor + from urllib2 import Request + from urllib2 import HTTPError + from urllib2 import URLError +else: + import urllib2 + from urllib2 import build_opener + from urllib2 import HTTPCookieProcessor + from urllib2 import Request + from urllib2 import HTTPError + from urllib2 import URLError class TestManufacturers(unittest.TestCase): """ Test the manufacturer data files are valid.""" @@ -66,7 +85,7 @@ def test_ManufacturerLinks(self): esta_id, name = manufacturer_data esta_ids.add(esta_id) - opener = urllib2.build_opener(urllib2.HTTPCookieProcessor()) + opener = build_opener(HTTPCookieProcessor()) for manufacturer_link in self.links: self.assertEqual(tuple, type(manufacturer_link)) @@ -92,7 +111,7 @@ def test_ManufacturerLinks(self): ua = {'User-Agent': 'Mozilla/5.0 (KHTML, like Gecko)', 'referer': 'http://example.com'} - request = urllib2.Request(link, headers=ua) + request = Request(link, headers=ua) response = opener.open(request) except URLError as e: if hasattr(e, 'reason'): From c45cebb9828221139f05d9e4994202bb157518e5 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 28 Jun 2026 12:12:05 +0100 Subject: [PATCH 07/24] Update some manufacturer links --- data/manufacturer_links.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/data/manufacturer_links.py b/data/manufacturer_links.py index 90ea831d..683bac9b 100644 --- a/data/manufacturer_links.py +++ b/data/manufacturer_links.py @@ -27,7 +27,7 @@ (0x00A8, "https://www.eye.co.jp/"), (0x00A9, "http://www.richter-lt.de"), (0x00B0, "http://www.arenaluci.com/"), - (0x00B9, "http://en.gzsjlight.com/"), + # (0x00B9, "http://en.gzsjlight.com/"), # Website currently gone (0x0104, "https://www.blizzardpro.com/"), (0x01CC, "https://portmanlights.com/"), (0x01CD, "http://www.compulite.com/"), @@ -52,7 +52,7 @@ (0x056B, "https://www.cosmolight.it/"), (0x056C, "https://lumascape.com/"), (0x05E0, "https://github.com/someweisguy/esp_dmx"), - (0x0609, "https://www.pierlite.com.au/diginet"), + (0x0609, "https://pierlite.com.au/our-brands/diginet"), (0x06E4, "https://www.dydell.com/"), (0x0710, "https://dts-lighting.it/"), (0x074F, "https://www.panasonic.com/"), @@ -70,7 +70,7 @@ (0x08A4, "https://www.adamhall.com/"), (0x08A6, "https://impulswerk.de"), (0x08EA, "https://www.cedarled.com/"), - (0x08C5, "https://ehrgeiz.glp.de/"), + # (0x08C5, "https://ehrgeiz.glp.de/"), # Now part of GLP (0x0956, "https://www.expromo.eu/"), (0x0957, "https://www.whitelight.ltd.uk/"), (0x0960, "https://fineline.solutions/"), @@ -134,17 +134,17 @@ (0x4C73, "http://www.lsclighting.com/"), (0x4D41, "http://www.malighting.com/"), (0x4D44, "https://www.mdgfog.com/"), - (0x4D50, "http://www.martin.com/"), - (0x4D56, "http://www.avolites.com/"), + (0x4D50, "https://www.martin.com/"), + (0x4D56, "https://www.avolites.com/"), (0x4F43, "https://www.offstagecontrols.com/"), (0x5000, "http://www.orangepi-dmx.org"), (0x5041, "http://www.lighting.philips.com/"), - (0x5075, "http://pulsarlight.com/"), + # (0x5075, "http://pulsarlight.com/"), # Website has gone (0x5100, "https://www.luxibel.com/"), - (0x514D, "http://www.qmaxz.com/"), - (0x5168, "http://www.sunricher.com"), + # (0x514D, "http://www.qmaxz.com/"), # Website had gone + (0x5168, "https://www.sunricher.com"), (0x5201, "https://www.crestron.com/"), - (0x5252, "http://www.rosco.com/"), + (0x5252, "https://www.rosco.com/"), (0x5253, "https://www.robe.cz/"), (0x5343, "https://www.oceaninsight.com/"), (0x5344, "https://www.stardraw.com/"), From 494c3c873f87b7454d3c535c42b93987e4da8b1b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 28 Jun 2026 13:58:32 +0100 Subject: [PATCH 08/24] Add additional links to HTTP error handling test --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 2076b9a7..c41deeaf 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -108,7 +108,8 @@ def test_ManufacturerLinks(self): (type(e) is HTTPError and (link == 'http://www.compulite.com/' or link == 'https://www.lutron.com/en-US/Pages/default.aspx' or - link == 'https://www.panasonic.com/'))): + link == 'https://www.panasonic.com/' or + link == 'https://www.acuitybrands.com/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From 6445feca9622cf2bbee421c40748d1611f7419d1 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 28 Jun 2026 14:13:46 +0100 Subject: [PATCH 09/24] Add NXP link to manufacturer test case --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 1392f336..18609ef6 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -130,7 +130,8 @@ def test_ManufacturerLinks(self): (link == 'http://www.compulite.com/' or link == 'https://www.lutron.com/en-US/Pages/default.aspx' or link == 'https://www.panasonic.com/' or - link == 'https://www.acuitybrands.com/'))): + link == 'https://www.acuitybrands.com/' or + link == 'https://www.nxp.com/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From 4db2ae3a47c0a00476d826e2a1b1469a494748d4 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 28 Jun 2026 14:17:14 +0100 Subject: [PATCH 10/24] Update manufacturer URLs for accuracy --- data/manufacturer_links.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/manufacturer_links.py b/data/manufacturer_links.py index 683bac9b..e4d86ba9 100644 --- a/data/manufacturer_links.py +++ b/data/manufacturer_links.py @@ -25,8 +25,8 @@ (0x00A2, "http://www.empdesigns.co.uk/"), (0x00A7, "https://www.syncronorm.com/"), (0x00A8, "https://www.eye.co.jp/"), - (0x00A9, "http://www.richter-lt.de"), - (0x00B0, "http://www.arenaluci.com/"), + (0x00A9, "http://www.richter-lt.de/"), + (0x00B0, "https://arenaluci.it/"), # (0x00B9, "http://en.gzsjlight.com/"), # Website currently gone (0x0104, "https://www.blizzardpro.com/"), (0x01CC, "https://portmanlights.com/"), From 67cce8c310010922fe94694538bb5e30aff9c0b9 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 29 Jun 2026 11:30:04 +0100 Subject: [PATCH 11/24] Update a few more manufacturer websites --- data/manufacturer_links.py | 6 +++--- data/manufacturer_test.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/data/manufacturer_links.py b/data/manufacturer_links.py index e4d86ba9..79da2fa7 100644 --- a/data/manufacturer_links.py +++ b/data/manufacturer_links.py @@ -26,7 +26,7 @@ (0x00A7, "https://www.syncronorm.com/"), (0x00A8, "https://www.eye.co.jp/"), (0x00A9, "http://www.richter-lt.de/"), - (0x00B0, "https://arenaluci.it/"), + (0x00B0, "https://arenaluci.it/en/"), # (0x00B9, "http://en.gzsjlight.com/"), # Website currently gone (0x0104, "https://www.blizzardpro.com/"), (0x01CC, "https://portmanlights.com/"), @@ -157,11 +157,11 @@ (0x544C, "http://tempest.biz/"), (0x564C, "http://www.vari-lite.com/"), (0x5753, "http://wirelessdmx.com"), - (0x5759, "https://www.wybron.com/"), + # (0x5759, "https://www.wybron.com/"), # Company, and website has gone (0x586D, "http://www.doityourselfchristmas.com/"), (0x6019, "https://artificers.co.uk/"), (0x6205, "http://www.ltechonline.com/"), - (0x6364, "http://www.lanbox.com/"), + # (0x6364, "http://www.lanbox.com/"), # Website has gone (0x646F, "https://www.eldoled.com/"), (0x6555, "https://shanteacontrols.com/"), (0x656C, "https://www.elclighting.com/"), diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 18609ef6..aaa806d6 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -131,7 +131,8 @@ def test_ManufacturerLinks(self): link == 'https://www.lutron.com/en-US/Pages/default.aspx' or link == 'https://www.panasonic.com/' or link == 'https://www.acuitybrands.com/' or - link == 'https://www.nxp.com/'))): + link == 'https://www.nxp.com/' or + link == 'https://www.martin.com/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From fc0aedaca84e4241da822c7b334128526033415c Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 30 Jun 2026 23:33:25 +0100 Subject: [PATCH 12/24] Add new link to skip during manufacturer test --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index aaa806d6..647caffe 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -132,7 +132,8 @@ def test_ManufacturerLinks(self): link == 'https://www.panasonic.com/' or link == 'https://www.acuitybrands.com/' or link == 'https://www.nxp.com/' or - link == 'https://www.martin.com/'))): + link == 'https://www.martin.com/' or + link == 'https://www.productionwarehouse.co.za/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From 29eb495dae0b664329946e5a23b3b0ae8d31e82f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 5 Jul 2026 12:29:37 +0100 Subject: [PATCH 13/24] Change assertion to allow response codes of 200 or 202 --- data/manufacturer_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 647caffe..f8552602 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -142,7 +142,7 @@ def test_ManufacturerLinks(self): if hasattr(e, 'errno'): self.fail("Link %s failed due to socket error %s" % (link, e.errno)) else: - self.assertEqual(response.code, 200, + self.assertTrue(((response.code == 200) || (response.code == 202)), "Failed to fetch URL %s got status %d" % (link, response.code)) From 0897b21bdeb64261fa02a22a3910426fa6c3d7c0 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 5 Jul 2026 13:22:12 +0100 Subject: [PATCH 14/24] Fix a syntax error --- data/manufacturer_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index f8552602..240e863b 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -142,7 +142,7 @@ def test_ManufacturerLinks(self): if hasattr(e, 'errno'): self.fail("Link %s failed due to socket error %s" % (link, e.errno)) else: - self.assertTrue(((response.code == 200) || (response.code == 202)), + self.assertTrue(((response.code == 200) or (response.code == 202)), "Failed to fetch URL %s got status %d" % (link, response.code)) From dfc61fd8771ae992b021f230384c20335a35e392 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 5 Jul 2026 13:24:36 +0100 Subject: [PATCH 15/24] Skip another URL --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 240e863b..66ccf176 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -133,7 +133,8 @@ def test_ManufacturerLinks(self): link == 'https://www.acuitybrands.com/' or link == 'https://www.nxp.com/' or link == 'https://www.martin.com/' or - link == 'https://www.productionwarehouse.co.za/'))): + link == 'https://www.productionwarehouse.co.za/' or + link == 'https://portmanlights.com/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From eed3831588693440bb1f368187e93bbf487ad13b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 5 Jul 2026 13:27:21 +0100 Subject: [PATCH 16/24] Skip https://www.adamhall.com/ URL --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 66ccf176..b5bf60c6 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -134,7 +134,8 @@ def test_ManufacturerLinks(self): link == 'https://www.nxp.com/' or link == 'https://www.martin.com/' or link == 'https://www.productionwarehouse.co.za/' or - link == 'https://portmanlights.com/'))): + link == 'https://portmanlights.com/' or + link == 'https://www.adamhall.com/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From cb11fcf5e4b555817ce7a22920bff4c50bcb4d2b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 5 Jul 2026 13:35:29 +0100 Subject: [PATCH 17/24] https://www.productionwarehouse.co.za/ is a different type of timeout error on CI --- data/manufacturer_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index b5bf60c6..196b185f 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -133,9 +133,10 @@ def test_ManufacturerLinks(self): link == 'https://www.acuitybrands.com/' or link == 'https://www.nxp.com/' or link == 'https://www.martin.com/' or - link == 'https://www.productionwarehouse.co.za/' or link == 'https://portmanlights.com/' or - link == 'https://www.adamhall.com/'))): + link == 'https://www.adamhall.com/')) or + (type(e) is URLError and + (link == 'https://www.productionwarehouse.co.za/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From 1bbfa4c2cc24959e65f9bdf51eec60afd486395f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 17:33:17 +0100 Subject: [PATCH 18/24] Update a few manufacturer URLs in manufacturer_links.py --- data/manufacturer_links.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/manufacturer_links.py b/data/manufacturer_links.py index 79da2fa7..923ab94a 100644 --- a/data/manufacturer_links.py +++ b/data/manufacturer_links.py @@ -131,8 +131,8 @@ (0x4C52, "https://www.highend.com/"), (0x4C53, "http://lss-lighting.de/"), (0x4C55, "https://lumenradio.com/"), - (0x4C73, "http://www.lsclighting.com/"), - (0x4D41, "http://www.malighting.com/"), + (0x4C73, "https://www.lsccontrol.com.au/"), + (0x4D41, "https://www.malighting.com/"), (0x4D44, "https://www.mdgfog.com/"), (0x4D50, "https://www.martin.com/"), (0x4D56, "https://www.avolites.com/"), From fd0274f8e0e9c916c4555c70f5977b68243cd857 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 18:13:58 +0100 Subject: [PATCH 19/24] Update manufacturer link for Fineline Solutions --- data/manufacturer_links.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/manufacturer_links.py b/data/manufacturer_links.py index 923ab94a..44c3070f 100644 --- a/data/manufacturer_links.py +++ b/data/manufacturer_links.py @@ -73,7 +73,7 @@ # (0x08C5, "https://ehrgeiz.glp.de/"), # Now part of GLP (0x0956, "https://www.expromo.eu/"), (0x0957, "https://www.whitelight.ltd.uk/"), - (0x0960, "https://fineline.solutions/"), + (0x0960, "https://fineline.uk.com/"), (0x097A, "http://teamboyce.com/"), (0x097F, "https://raumzeitlabor.de/"), (0x0984, "https://www.laserworld.com/"), From d29f0a3923f478d38fa973037685ad264c8d047a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 18:43:56 +0100 Subject: [PATCH 20/24] Comment out teamboyce.com entry in manufacturer_links Comment out the entry for teamboyce.com due to website unavailability. --- data/manufacturer_links.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/manufacturer_links.py b/data/manufacturer_links.py index 44c3070f..7d748caf 100644 --- a/data/manufacturer_links.py +++ b/data/manufacturer_links.py @@ -74,7 +74,7 @@ (0x0956, "https://www.expromo.eu/"), (0x0957, "https://www.whitelight.ltd.uk/"), (0x0960, "https://fineline.uk.com/"), - (0x097A, "http://teamboyce.com/"), + # (0x097A, "http://teamboyce.com/"), # Website has gone (0x097F, "https://raumzeitlabor.de/"), (0x0984, "https://www.laserworld.com/"), (0x0987, "https://www.mathertel.de/"), From 01da90e44d64ac0948b30426e1fb9f616f7eafb7 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 20:03:42 +0100 Subject: [PATCH 21/24] Skip another working, but failing the tests, link --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 196b185f..31a4d9de 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -134,7 +134,8 @@ def test_ManufacturerLinks(self): link == 'https://www.nxp.com/' or link == 'https://www.martin.com/' or link == 'https://portmanlights.com/' or - link == 'https://www.adamhall.com/')) or + link == 'https://www.adamhall.com/' or + link == 'https://www.offstagecontrols.com/')) or (type(e) is URLError and (link == 'https://www.productionwarehouse.co.za/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) From ce50bdca25e2b404c228edba184b28f3faf70c16 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 20:54:45 +0100 Subject: [PATCH 22/24] Correct the error type we're skipping offstagecontrols against --- data/manufacturer_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index 31a4d9de..aaaee0dc 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -134,10 +134,10 @@ def test_ManufacturerLinks(self): link == 'https://www.nxp.com/' or link == 'https://www.martin.com/' or link == 'https://portmanlights.com/' or - link == 'https://www.adamhall.com/' or - link == 'https://www.offstagecontrols.com/')) or + link == 'https://www.adamhall.com/')) or (type(e) is URLError and - (link == 'https://www.productionwarehouse.co.za/'))): + (link == 'https://www.productionwarehouse.co.za/' or + link == 'https://www.offstagecontrols.com/'))): self.fail("Link %s failed due to %s, reason type: %s" % (link, e.reason, type(e))) elif hasattr(e, 'code'): self.fail("The server couldn't fulfill the request for %s. Error " From ae617474aae091de2f5ac3209d28280342067f1f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 22:54:26 +0100 Subject: [PATCH 23/24] Skip Eldo LED in manufacturer test cases --- data/manufacturer_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/manufacturer_test.py b/data/manufacturer_test.py index aaaee0dc..9a332026 100644 --- a/data/manufacturer_test.py +++ b/data/manufacturer_test.py @@ -134,7 +134,8 @@ def test_ManufacturerLinks(self): link == 'https://www.nxp.com/' or link == 'https://www.martin.com/' or link == 'https://portmanlights.com/' or - link == 'https://www.adamhall.com/')) or + link == 'https://www.adamhall.com/' or + link == 'https://www.eldoled.com/')) or (type(e) is URLError and (link == 'https://www.productionwarehouse.co.za/' or link == 'https://www.offstagecontrols.com/'))): From eb31a348b014bc9b1e75beeba97c07e1909d32bb Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 14 Sep 2026 23:27:49 +0100 Subject: [PATCH 24/24] Switch the model_data to hex for maximum compatibility --- data/model_data.py | 82 +++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/data/model_data.py b/data/model_data.py index bc5f0260..a5affbf8 100644 --- a/data/model_data.py +++ b/data/model_data.py @@ -18,47 +18,47 @@ # Data for the device models. DEVICE_MODEL_DATA = { - 8482L: [{'device_model': 38, - 'model_description': 'LED BAR', - 'product_category': 1289, - 'software_versions': {1: {'languages': [], - # 'label': 'V1.02 \x00LED BAR\x00BRITEQ', - 'manufacturer_pids': [], - 'personalities': [{'description': ' \x00\x08', - 'index': 1, - 'slot_count': 3}, - {'description': ' \x00\x08', - 'index': 2, - 'slot_count': 4}, - {'description': ' \x00\x08', - 'index': 3, - 'slot_count': 5}, - {'description': ' \x00\x08', - 'index': 4, - 'slot_count': 6}, - {'description': ' \x00\x08', - 'index': 5, - 'slot_count': 12}, - {'description': ' \x00\x08', - 'index': 6, - 'slot_count': 15}, - {'description': ' \x000', - 'index': 7, - 'slot_count': 16}], - 'sensors': [{'description': 'Temperature', - 'index': 0, - 'supports_recording': 0, - 'type': 0}], - 'supported_parameters': [512, - 513, - 128, - 129, - 130, - 224, - 225, - 1024]}}, - 'sub_device_count': 0}], - 25711L: [{'device_model': 30, + 0x2122: [{'device_model': 38, + 'model_description': 'LED BAR', + 'product_category': 1289, + 'software_versions': {1: {'languages': [], + # 'label': 'V1.02 \x00LED BAR\x00BRITEQ', + 'manufacturer_pids': [], + 'personalities': [{'description': ' \x00\x08', + 'index': 1, + 'slot_count': 3}, + {'description': ' \x00\x08', + 'index': 2, + 'slot_count': 4}, + {'description': ' \x00\x08', + 'index': 3, + 'slot_count': 5}, + {'description': ' \x00\x08', + 'index': 4, + 'slot_count': 6}, + {'description': ' \x00\x08', + 'index': 5, + 'slot_count': 12}, + {'description': ' \x00\x08', + 'index': 6, + 'slot_count': 15}, + {'description': ' \x000', + 'index': 7, + 'slot_count': 16}], + 'sensors': [{'description': 'Temperature', + 'index': 0, + 'supports_recording': 0, + 'type': 0}], + 'supported_parameters': [512, + 513, + 128, + 129, + 130, + 224, + 225, + 1024]}}, + 'sub_device_count': 0}], + 0x646F: [{'device_model': 30, # 'model_description': 'LinearDC720W', 'product_category': 1289, 'software_versions': {254: {'label': '254',