Development would be easier if we have a dummy driver for the camera device and the serial connection. Such drivers would allow to run the FabScanPi-Server without the hardware.
https://github.com/mariolukas/FabScanPi-Server/tree/develop/src/fabscan/scanner/laserscanner/driver
What i have in my mind is:
Dummy cam driver:
A camera class which is implemented such as the one for the picamera, but it should grab the images from a folder instead of a camera. This folder should keep different plain pictures which i will make with the fabscan hardware. One set during a scan and one set during the settings window is opened.
Serial dummy driver:
The serial driver is quite easy, it should be a the serial driver as it is now but only as a stub/mock which will do nothing expect to confirm that the message was send.
Both dummy drivers should be encapsulated in a way that you can set the driver in the config. There is already something like that for the camera driver, because in an early stage of implementing that i experimented to write a driver for usb cams (parts of this code are still there).
I think that might be an excellent entry point for you and it will help us all and especially the guy who is developing the current frontend version because he does not own a working hardware setup at the moment. I would appreciate that.
By the way we are the only core developers by now :)
I'm used to doing this in C# moving entry points to services implementing interfaces so they can be implemented by mocks or by real backends. Not sure what the typical approach is in python. Are we moved to python3? Do I just clone the project and go to town?
Yah, it seems like a stub would be more useful than a mock inside of a formal testing framework. I went ahead and got PyCharm Pro -- the monthly fee is reasonable and using the same tools as yours will likely save more than the $8 / month in frustration.
How do you go about launching the dev code headless? What's your typical work flow when running the code?
I will add a dev setup guide with screenshots to the documentation this evening. (8:00 pm CET).
I'm happy to help with the doc FYI, if the steps aren't to complex to figure out, I'd be happy to document them as I go.
So, now that I have the dev env set up, I can go ahead and start with the testing work. Is this a viable guide to get started? Seems pretty straightforward, but I haven't dug into the implementations of the classes.
https://www.jetbrains.com/help/pycharm/testing-your-first-python-application.html
I can start with an empty test and start building as I go. If I have to refactor anything, where are you currently working so I am less likely to step on any toes?
So, now that I have the dev env set up, I can go ahead and start with the testing work. Is this a viable guide to get started? Seems pretty straightforward, but I haven't dug into the implementations of the classes.
Yes you can go with it. There are already some tests in the test folder. ( Yes shame on me for only writing a few tests over all years i am working on FabScan now ? )
I can start with an empty test and start building as I go. If I have to refactor anything, where are you currently working so I am less likely to step on any toes?
I think i am preparing the upcoming release ( the current python3 feature branch). Afterwards i will do some work on the new UI. So i think there should ne no conflicts. Otherwise we can keep each other up to date.
Start by forking the project and create a new feature branch. I will keep you informed when you need to merge the current dev branch into your feature branch ( when it is nessesary).
I think the best starting point is the serial driver. This is the easiest task. The "dummy" only needs to pass the command without doing real sending. The real hardware/FabScanPi HAT returns an ACK when the command was executed (motor movement, laser switching, led on/off). The ACK is just an echo of the command which was sent to the HAT.
So the serial dummy driver should just implement the callable functions which are provided by the real serial driver class. The functions should return fake data ( e.g. for requesting version number) or fake ACK signals ( directly passing through the G-Code command by the return statement).
Further thoughts (does not affect the camera parts):
I am planing to encapsulate the serial driver in a more general/generic approach. Because future versions of the FabScanPi Server should be able to handle also Raspberry Pi GPIO's Pins instead of a serial connection to a microcontroller. There are some scanners which are able to control the hardware over thee GPIO's. So i am thinking about a abstraction layer ( proxy pattern) for handling different hardware types for hardware controlling. Something like a class called connector would be great which implements a factory for creating an instance of the current needed control unit ( FSSerial.py, FSGPIO.py). The protocol and interface should be the same so that the FSLaser, FSTurntable, FSLed classes send the command as it is and the instantiated connector implementation handles sending/executing depending on which type of hardware it uses. The connector can be configured by the default.config.json. There should be a configuration object which replaces the serial object. This approach can also be reliable and useful when we want to configure the dummy driver. Maybe we should start with this layer of abstraction for the hardware communication.
"serial": {
"plattform_type": "fabscanpi",
"baudrate": 115200,
"autoflash": "True",
"flash_baudrate": 115200,
"port": "/dev/ttyAMA0"
},
should be something like (for serial)
"connector": {
"type: "serial",
"config: {
"plattform_type": "fabscanpi", <--- needed by the serial driver to detect the current uses hardware
"baudrate": 115200,
"autoflash": "True",
"flash_baudrate": 115200,
"port": "/dev/ttyAMA0"
}
},
should be something like (for GPIO)
"connector": {
"type: "gpio",
"config: {
gpio_laser_0: xx
gpio_laser_1: xx
gpio_turntable_step: xx
gpio_turntable_dir: xx
gpio_led: xx
}
},
and finally of course the dummy driver:
"connector": {
"type: "serial_dummy",
"config: {
"plattform_type": "fabscanpi",
"baudrate": 115200,
"autoflash": "True",
"flash_baudrate": 115200,
"port": "/dev/ttyAMA0"
}
},
This also keeps the gate open for other connection types like i2c,spi etc.