Missing devices.json when packing script with pyinstaller
Trying to compile and pack any script with BAC0, the packed executable (for distribution to others) is not working as the device.json file is missing:
>pyinstaller test.py
>test.exe
2025-11-09 20:40:48,463 - INFO | Starting Asynchronous BAC0 version 2025.09.15 (Lite)
2025-11-09 20:40:48,465 - INFO | Using bacpypes3 version 0.0.102
2025-11-09 20:40:48,466 - INFO | Use BAC0.log_level to adjust verbosity of the app.
2025-11-09 20:40:48,466 - INFO | Ex. BAC0.log_level('silence') or BAC0.log_level('error')
2025-11-09 20:40:48,492 - INFO | Using ip : 10.10.82.223/24 on port 47808 | broadcast : 10.10.82.255
2025-11-09 20:40:49,305 - INFO | Using default JSON configuration file
2025-11-09 20:40:49,306 - ERROR | BAC0.scripts.Lite | Lite | BAC0.scripts.Base | an error has occurred: [Errno 2] No such file or directory: 'C:\\Users\\me\\Documents\\BacnEx\\dist\\test\\_internal\\BAC0\\core\\app\\device.json'
The issue is there with and without the --onefile option.
In facts, that device.json file is not packed -- it is not present in the _internal directory.
One solution is to copy it manually to C:\users\myuser.BAC0 directory -- but it is quite complicated for an unexperienced user I'd like to distribute the executable to.
I've found a better solution: specifying explicitly the file to be packed together:
>pyinstaller.exe --onefile --add-data .venv\Lib\site-packages\BAC0\core\app\device.json:BAC0/core/app test.py
It works fine, both with and without the --onefile option
However, it should be better to "instruct" the BAC0 package in some way that the device.json file needs to be included. I'm not so skilled in python so I didn't find the correct solution -- but I'm quite sure it IS possible in some way to do so, as the "pytz" package (that is also needed with BAC0) automatically adds its own whole zoneinfo directory to the _internal folder automatically.
Interesting use case... At first, device.json was meant to be optional.... as normally there should be a copy in the package.... Let me look at it
What would you put in the file in your app ?
Ah, ok. I thought the file is used just to define local device defaults. In facts, I feel no need to modify its content.
However, when it's missing, the error is critical and BAC0 stops immediately. Thus the need to include it in the compiled pack. I've seen its path is defined in the asyncApp.py file (first it looks in the user/.BAC0 folder, then in its default location). Maybe it could also be searched in the script folder itself. Or, better, add an optional parameter to BAC0.start to define its position when needed.
However (if it continues to be a must for a working BAC0), I think it would be nice to have it packed by default inside the compiled version. At least for us, Windows users ;-)