bengtmartensson / HarcHardware

HarcHardware is a collection of Java routines for accessing hardware, files, network resources etc.
http://www.harctoolbox.org/HarcHardware.html
GNU General Public License v3.0
3 stars 4 forks source link

Add hardware support: Flipper Zero-ONE [STALLED] #26

Open Msprg opened 2 years ago

Msprg commented 2 years ago

Hello!

I would like to add hardware support for Flipper Zero. It's a multi-tool device with many capabilities, including receiving and transmitting Ir signals. The communication can be accomplished by utilizing a serial connection over USB.

I have already managed to set up a build environment that can produce working IrScrutinizer builds. However, I'm having difficulties as to where and how to begin implementing this feature. My initial plan was to basically clone the "Girs Client" (For Arduino) part for example, and then rework it to make it able to communicate with the Flipper instead.

Unfortunately, I'm at a loss, as I failed to locate parts of the code responsible for the communication with the HW devices, so I can't even examine them, to begin with.

I believe that for the most part ill be able to implement this myself, but I could really use a helping hand.

bengtmartensson commented 2 years ago

Hi,

Hardware communications is done in the support project HarcHardware, which is possibly why you did not find it. I have transferred the issue accordingly.

To add a new IR device, just write a class that implements one or more of the interfaces ICapture, IrReceive, IRawIrSender, etc.

Once you have it running in that context, it is easy to add it to the IrScrutinizer GUI.

Msprg commented 2 years ago

Thank you.


I found the relevant java files, and I am now attempting to make an IrFlipperZero class based on IrToy class since it seems to be more similar to the Flipper than the Girs one.

Initially, I plan to get the receiving part working. After that works, the next step would be to implement signal transmission. After that, if Ill get some spare time on my hands, I might add in import/export to the Flipper compatible formats.

But let's not get ahead of myself.

I would like to ask you some noob questions:

The serialPort instance has the following method signatures:

byte[] readBytes(int length)
int readBytes(byte[] buf)
int readByte()

How would I go about using them to read to a buffer variable until the EOF (end of the current output) ? I'm asking because I haven't found any documentation about them in the code.

Another question I would like to ask is what options I have for testing my code without adding it to the GUI beforehand. I already found out that HarcHardware is a utility that can be used in a terminal however I have failed to comprehend how would I go about initializing a session with a specific device and thus executing my parts of the code. The only other way I see is to just make a temporary test class that would have a runnable main function where I would be testing my code.

bengtmartensson commented 2 years ago

The serialPort instance has the following method signatures:

byte[] readBytes(int length) int readBytes(byte[] buf) int readByte()

How would I go about using them to read to a buffer variable until the EOF (end of the current output) ?

Smell of C, rite? Writing into a fixed buffer supplied by the caller? Feel free to use the class org.harctoolbox.harchardware.comm.LocalSerialPortBuffered instead; it has a readString() function...

Another question I would like to ask is what options I have for testing my code without adding it to the GUI beforehand.

Use org.harctoolbox.harchardware.Main.main(...). For example

java -jar HarcHardware-*.jar-with-dependencies --class IrFlipperZero ... capture --decode --raw

will capture a signal using the said class, try to decode it, and print the raw version too, and then exit.

The argument of --class is read using reflections, so no need to tell Main about IrFlipperZero.

Msprg commented 2 years ago

Thank you for being so helpful so far!

I have managed to get some "prototype / PoC" code working to successfully get Flipper to receiving mode, receive, and parse Flipper's output for the RAW protocol successfully.

This progress has uncovered the following issues:

  1. It seems Flipper always sends an odd number of values for RAW signals. For the remote I have available for testing purposes, this usually means 99, 199, 299, ...etc. samples, thus causing an exception. It's "fixable" by, for example, hardcoding the appendix of a " 0" at the end of the flipper output. It doesn't seem to be an optimal solution, however, I failed to come up with any better approach so far. Any ideas? (note: it seems that decode is inconsistently(?) working with this fix. With more repetitions, recognition gets better of course. )

    LocalSerialPortBuffered.readString: received "RAW, 199 samples:"
    LocalSerialPortBuffered.readString: received "3463 1711 448 448 417 1321 421 421 444 452 424 445 420 449 416 425 451 446 419 449 416 453 423 446 419 449 416 453 423 1288 443 453 423 446 419 450 415 453 423 446 419 423 442 454 422 1288 443 453 423 1316 415 454 422 447 418 1320 422 1290 441 1297 445 451 425 444 421 448 417 452 424 1286 445 1294 448 448 417 452 424 445 420 449 416 452 424 445 420 1291 451 445 420 1318 424 1288 443 1295 530 340 442 1322 420 74742 3456 1719 450 419 446 1319 422 446 419 450 415 454 422 447 418 451 414 454 422 447 418 451 414 454 422 448 417 451 425 1286 445 451 425 445 420 448 417 452 424 445 420 448 417 452 424 1287 444 452 424 1314 417 452 424 445 420 1291 451 1287 444 1294 447 449 416 453 423 446 419 450 415 1322 420 1319 423 446 419 450 415 454 422 447 418 450 415 454 422 1316 415 454 422 1289 442 1323 419 1293 449 447 418 1293 448 "
    Freq=38000Hz[+3463,-1711,+448,-448,+417,-1321,+421,-421,+444,-452,+424,-445,+420,-449,+416,-425,+451,-446,+419,-449,+416,-453,+423,-446,+419,-449,+416,-453,+423,-1288,+443,-453,+423,-446,+419,-450,+415,-453,+423,-446,+419,-423,+442,-454,+422,-1288,+443,-453,+423,-1316,+415,-454,+422,-447,+418,-1320,+422,-1290,+441,-1297,+445,-451,+425,-444,+421,-448,+417,-452,+424,-1286,+445,-1294,+448,-448,+417,-452,+424,-445,+420,-449,+416,-452,+424,-445,+420,-1291,+451,-445,+420,-1318,+424,-1288,+443,-1295,+530,-340,+442,-1322,+420,-74742,+3456,-1719,+450,-419,+446,-1319,+422,-446,+419,-450,+415,-454,+422,-447,+418,-451,+414,-454,+422,-447,+418,-451,+414,-454,+422,-448,+417,-451,+425,-1286,+445,-451,+425,-445,+420,-448,+417,-452,+424,-445,+420,-448,+417,-452,+424,-1287,+444,-452,+424,-1314,+417,-452,+424,-445,+420,-1291,+451,-1287,+444,-1294,+447,-449,+416,-453,+423,-446,+419,-450,+415,-1322,+420,-1319,+423,-446,+419,-450,+415,-454,+422,-447,+418,-450,+415,-454,+422,-1316,+415,-454,+422,-1289,+442,-1323,+419,-1293,+449,-447,+418,-1293,+448,-0][][]
    Panasonic: {D=160,S=28,F=6}, beg=0, end=99, reps=1 {UNDECODED. length=100}
  2. The LocalSerialPortBuffered class seems to be a much better fit for the task at hand, but I have noticed one peculiar thing: I needed to clear/flush the input / incoming serial data buffer, but flush() nor flushInput() have appeared to be working for me, so I just made myself a helper function to clear buffer by calling readString() until it returns null. It seems that this idea is working overall but despite its setting to not wait for the input, It just hangs in particular circumstances (always at/after the same line of serial output - haven't investigated further) in the same way as if the wait was set to true. It then - in verbose mode - even reports back TIMEOUT. I'm guessing it has something to do with bufferedInStream.ready() on the line 112 of LocalSerialPortBuffered.java but for all I know, I might be just using it wrong.

Overall, progress goin' slowly but surely ;)

bengtmartensson commented 2 years ago
  1. Im my world, IR sequences (class IrSequence) always have an even number of durations. If it is returned from a receiving/capturing device, the last duration (which is a gap/space) has the following semantics: The receiver has waited this long, and verified that nothing was sent, see this and the endingTimeout parameter in Infrared4Arduino. Other communities, for example Linux/Lirc, consider an IR sequence to consists of an odd number of durations, i.e. no ending gap. Ideally, you should find out what your hardware is using, and append that as the final gap. But it is ok to guess, say 100ms. (But 0 is never ok as a duration!)
  2. I cannot really relate to the verbal description; I suggest that you check in your preliminary work in a branch of your fork, so we can have a look at that.
Msprg commented 2 years ago

Hi,

Thank you for all the useful info! I have made some workarounds about the LocalSerialPortBuffered issues, mainly by changing timeouts. Just to reiterate - the gist of the issues is 1. flushInput(); appears to be ineffective, 2. serialPort.readString(false); hangs in certain circumstances // appears to be waiting despite boolean wait is set to false, and then returns null (timeout) anyway.

I will look into the last duration issue, and replace the adding 0 with something more sensible later.

It might be about time for you to see my code for the first time, as the very basic functionality already appears to be working correctly. You can find my work in my fork in a new branch. I hope I did branching etc. correctly since currently I have basically no experience contributing to F/OSS.

bengtmartensson commented 2 years ago

Sorry, I have not yet scrutinized your code. Is there some serial port API description you are using? Anyhow, sending Ctrl-C over the serial port is not a "standard method".

Moreover, I I do not consider the Flipper to be a very attractive device to capture IR signals. It contains (only) a demodulating receiver (TSOP-75338 to be exact), removing the carrier and making exact measurements impossible. A serious IR uses a non-demodulating receiver (TSMP-58, OPL-551 , QSE15, etc). Consider for example my gadget.

Msprg commented 2 years ago

Is there some serial port API description you are using?

Not really. There are no specifics that would be deemed an API, I suppose. Despite that, I do not think the commands and responses have many reasons to change as they are now. Regarding this, I am also trying to write the code as independent of the output format as possible, not relying on literals if viable in the given context.

In case they would be subject to change in the future it should be pretty easy to adapt the code to the new changes, of course, depending on how extensive will the changes be. I may look into RPC and see if It would make sense to utilize it instead. If I won't forget.

It contains (only) a demodulating receiver...

I am aware of that. To be honest I am treating this as an opportunity to learn something new and give back (my first) tiny bit of contribution to the open source community. All that while practicing some programming skills. In case you would not approve of my work, or intentions, feel free to openly speak your mind.

Consider for example my gadget.

Oh, yes! In fact, I built one myself as per the instructions provided! I was just seeing an opportunity to try to integrate Flipper with the IrScrutinizer and took it.


In regards to development: The flipper provides already decoded data for protocols in its database. Currently, there is not an obvious way to, for example, always output RAW (skip decoding). I would like to ask for advice - what would be more feasible - encapsulating it somehow directly to some of the HarcHardware classes (I have not found any that would accept a protocol name and its values), or making a pull request to add a parameter to the official FZ firmware to skip the decoding and always output raw?

I suppose it would be the latter since HarcHardware does its own protocol parsing/decoding anyway. Either way, I would like to know your opinion on the matter.

Also, I wanted to add the FZ to the IrScrutinizer's GUI, but I am coding in IntelliJ and it can't even display the form files, and editing them by hand is proving somewhat tricky. Do I have to install eclipse IDE anyway solely for this purpose? (I am aware that the final GUI would have to be done in Eclipse anyway as per contribution guidelines, but I wanted to patch something simple together just for the sake of testing).

Msprg commented 1 year ago

Hello again,

I have been a bit busy with uni for a few weeks, however, the Flipper force RAW mode (no decode) has been added and I have also corrected appending the last gap. I consider the receiving part of my fork, besides maybe a bit of a cleanup, complete!

However, I do not plan on pulling to your repo until implementing the TX part as well. As soon as RX and TX will be finalized, I will open a pull request as I believe that this is all for the HarcHardware. (import/export is not handled by HarcHardware, I believe...)

Thank you for your guidance so far... If you would like, pay a visit to my fork on the FlipperZero1 branch. The code might not be up to your standards, but I did my best∼!

I just hope my work will be put to good use :)

bengtmartensson commented 1 year ago

Hi,

nice to hear from you again. I have ordered a Flipper myself; it should arrive any day now.

import/export is not handled by HarcHardware, I believe...)

Right. Export is described here, import is slightly less streamlined: You basically have to write a program that transforms the Flipper file into a file that can be read, for example girr or csv.

Msprg commented 1 year ago

Hi, nice to hear from you again.

Glad to hear from you as well!

I have ordered a Flipper myself; it should arrive any day now.

Can't wait to welcome you to the cyber dolphin family~!