nicsure / QuanshengDock

Allows the Quansheng UV-K5 radio to be controlled by a PC.
GNU General Public License v2.0
277 stars 23 forks source link

Not a bug. Refactoring needed? #58

Open mfp20 opened 7 months ago

mfp20 commented 7 months ago

Hi,

your project (and the availability of the awesome quansheng fully customizabile and cheap HW platform) convinced me to resurrect my old hamradio licence and start buying gear again. Thanks for the awesome job.

I'd like to add hamradio capabilities to my tech closet sitting right under my roof. The problem is I've headless ARM (R.Pi) and MIPS (Openwrt routers) machines, only, over there, not a windows machine (and can't place one there). So I need to "remote the radio". I have seen you have just released a new repo for a crossplatform version of the dock and it looks like you are using some sort of microsoft alchemy to produce the crossplatform app, but still... isn't a remote for an headless system.

Finally to the point: is it possible to refactor your project so that we can have a C/C++ library (ie: something easily built on any machine)? It would make your project fit to other use cases (as you are already doing to support other platforms) and more attractive for other developers (like me). I'm assuming some of your code interoperates with the firmware; that's the only part that must be in the library. Then any UI (cli, gui, whatever) can be rebased on top of the library. This kind of refactoring is boring, because there's the need to produce some boilerplate, but it would also reduce the time you need to maintain your project.

I'm willing to spend some time on the project myself but the firmware repo is too complex as well; it would take me too much time to figure out the protocol you are using to command the radio from the dock, find the peculiar caveats, and so on. A protocol description/definition would be enough for me to write the C/C++ library myself; but usually it's way better for the same firmware author to do the host library as well (example: Klipper firmware for 3D Printers). No other developer can have a better understanding of the core issue addressed by the code.

I understand I'm asking for a lot of commitment and I will understand if you wouldn't like to go down that road. I allowed myself to write this message just because the project is relatively young, so it's not too late to eastablish it in a way it would work as a reference for all the future works on this HW platform.

Regards

nicsure commented 7 months ago

At a basic protocol level, this is kind-of already the case for the firmware as there is an underlying serial communication system in place to control the radio. So while this is not an API, it's only one step lower.

The majority of users are basic Windows users. When you look at Linux, Android, MacOS etc.. sure there are some but they are dwarfed by Windows. It was abundantly clear to me from the video views that cross-platform was a waste of time. The amount of effort I put in on it is just not worth it for the amount of people who would actually use it. I could I guess do what you suggest, but for the dozen or so people who would actually utilize it, it would be a whole bunch of my time spent for next to nothing.

mfp20 commented 7 months ago

At a basic protocol level, this is kind-of already the case for the firmware as there is an underlying serial communication system in place to control the radio. So while this is not an API, it's only one step lower.

Yep, I saw the code you introduced in the firmware. It's incredible you needed to add so little code in order to achieve such a great result. Basically just a bit of custom commands in the uart, so that a remote gui can manipulate registers and update the display. But this means all the complexity is in the gui code.

The majority of users are basic Windows users. When you look at Linux, Android, MacOS etc.. sure there are some but they are dwarfed by Windows. It was abundantly clear to me from the video views that cross-platform was a waste of time. The amount of effort I put in on it is just not worth it for the amount of people who would actually use it. I could I guess do what you suggest, but for the dozen or so people who would actually utilize it, it would be a whole bunch of my time spent for next to nothing.

I feel you. It's the same exact reason I didn't commit on other projects as well and ... I imagine it is the same reason for existing a huge effort fragmentation in place, ie: gazillion small projects aiming at a single special-case result. If we take the quansheng firmware as an example, there have been a huge amount of mods scattered all around the net and ... hopefully someone will pack them together soon or later; it's already happening. But let me tell you what you see on the web isn't what it is for real. I mean ... I'm one of the viewers you recorded as "windows users" but I've about 15 linux/freebsd machines and 1 window machine (for web browsing and games, on a separate vlan with my mom's mobile phone and my neighbor's iphone).

I wait for the radio HW to get here and then decide wheter to commit some of my time on it. It doesn't look that complicate at first glance but I've seen the firmware code only, so most of the logic must be in the c-sharp gui. I've already ported some c-sharp stuff to C, so the porting itself isn't a problem. I'm afraid of figuring out procedures embedded in the gui. And I can't tx until I renew the licence.

Once ack'ed you can't spend more time on this; would you be willing to rebase the app on the library I make, in the case I proceed that way?

djex commented 7 months ago

What I guess might be useful is a daemon that can run cross platform which will communicate with the radio and offer up an API to connect to over a network.

Currently the code is using .NET 6 so coding a small program that serves up an API shouldn't be too difficult. .NET is cross platform even supporting ARM. This could work allowing anyone to code their own front end GUI that accesses the API over the network. Now this would be only for radio control but could be expanded on to also stream audio over the network as well.

nicsure commented 7 months ago

The QDNH project kind of does this. It interfaces with a radio via serial and audio input/output , then hosts these on a network server (single connection). A connecting system essentially has two network sockets for serial and audio. The interface is basically the serial protocol being used, you just need an API layer for that.

Were you not aware of QDNH?

mfp20 commented 7 months ago

What I guess might be useful is a daemon that can run cross platform which will communicate with the radio and offer up an API to connect to over a network.

Currently the code is using .NET 6 so coding a small program that serves up an API shouldn't be too difficult. .NET is cross platform even supporting ARM. This could work allowing anyone to code their own front end GUI that accesses the API over the network. Now this would be only for radio control but could be expanded on to also stream audio over the network as well.

The audio part is trivial. The standardization of network protocols gives you the crossplatform; that's the reason why we have IETF. You currently have the audio connected to the host sound device. At that point there's a gazillion softwares to route the audio to ... anywhere; moreover, modern silicons have huge FFT capabilities to compress, decompress, filter, and what not, all realtime. If you pick one existing app using a standard codec/signaling (ex: SIP+RTP+g722, just to name one in use for VOIP) then you'll have a gazillion options on any receiving client (ex: VLC runs on any device; ffmpeg, gstreamer... you name it). In other words if you use a standard protocol stack, you can develop the server part and don't be worried about the client one. If you want to give a full solution instead of just a component, you can glue togheter a bunch of libraries to offer a client as well. Moreover, the audio we are talking about is mono. Single channel out, single channel in. The only complexity is syncronicity (it's a human comm, so it must be syncronous), so if the devleoper fails about latency, it fails the project. And the serial data is trivial as well: it's low speed, it's serial (ie: data moves in order), it runs on medias not having noise levels or other analog alchemy, and ... there are a tons of options already available to have a serial port remoted via network protocols.

The only problem is .NET. And basically whatever else (ie: QT). Don't get me wrong: they are tech-good; Quandsheng Dock shows a pretty good result (and there are plenty great apps written using .NET or QT, ex: VScode). It is snappy, zero latency (ie: you click on computer and the radio react instantly), even nice to look at. And in the case of QT it would be equal. Problems arise later on: .NET doesn't integrate well, QT requires an expensive license for advanced and commercial uses. At some point during the life of any .NET/QT based project there will be some sort of blocking issue due to commercial/legal reasons. Denying the very nature of the project: to make something people can Freely make good use of.

As Nic already wrote: if users are 12 - and I add: the customizable radio is 1 only (and public authorities are already searching for whatever excuse to ban it... "too many harmonics!") - there's no point to waste time in packing and serving a good software. The day Quansheng will stop selling the HW, or those 12 windows monkeys will be attracted by some more fashinating blinken lights ... our today's commitment will be wasted. This is the reason why hamradio operators, since ever, are castrated into a hell made of tiny obscure pieces of softwares stitched together with duck tape and paper clips on windows computers joint with linux bits crammed in hyper-v and ... the only alternative being some good piece of software (like Quansheng Dock) for single use cases, made with RAD tools (.NET is a Rapid Application Development tool; ie: something that easily fit in developer's personal schedule).

At the end of the day, the only way to expand the use cases it is to make a message in the bottle (ie: a C/C++ library) and let it be...

mfp20 commented 7 months ago

Were you not aware of QDNH?

What's QDNH?

nicsure commented 7 months ago

Were you not aware of QDNH?

What's QDNH?

https://github.com/nicsure/QDNH

djex commented 7 months ago

Were you not aware of QDNH?

What's QDNH?

https://github.com/nicsure/QDNH

Ahh I was not aware of this project. Thanks for the link. I did find some references to it in the dock code but wasn't sure where the code for the server was.

Currently the code is using .NET 6 so coding a small program that serves up an API shouldn't be too difficult. .NET is cross platform even supporting ARM. This could work allowing anyone to code their own front end GUI that accesses the API over the network. Now this would be only for radio control but could be expanded on to also stream audio over the network as well....

Ahh .NET isn't that bad. It's completely fine in regards to a command line daemon / api server as mentioned. However I will agree with you when it comes to implementing a GUI for .NET applications it's a real pain having it properly cross platform. I guess what I was getting at was to keep things simple since the code is already in .NET 6 a minimal command line api server would be quick to code up using some existing code and then the front end could be coded in anything you desire. Looks like nicsure was already a step ahead however with QDNH.

mfp20 commented 7 months ago

Looks like nicsure was already a step ahead however with QDNH.

Fuck yeah!!! He is the hero! I'm really looking forward for my gear to arrive and get my hands dirty.

And QDNH code is very simple: grand total of 6 simple classes; a CLI shell, a multithreaded server, basic auth, uart, playback and record. Probably some complexity is hidden by .NET classes I'm not familiar with (ex: NetworkStream, BufferedWaveProvider, and so on), but that's style! At this point I'd say there's no need for the original author to do anything else. I mean: he added network capabilities to Dock and provided its counterpart, simple and easy to port, eventually. That's awesome.

The only question arises in my mind is: could it work with data (APRS, Packet Radio... DMR/FreeDV)? I haven't investigated the transceiver chip yet (modulation capabilities, rx/tx switching timings, and so on) but I don't see any real time control in the code; it seems like the audio is thrown as is to a FIFO-buffered PCM container, then served to the network, all best effort (ie: as long as the host cpu can make it, it does). That's good for audio purposes, but might be not enough for data timings.

nicsure commented 7 months ago

There is a tad more to the audio than just a FIFO. Since I didn't want to mess with UDP (support nightmare) I had to figure out a way send it over TCP and still deal with synchronization. The way that's done is for the sender of audio data to check if the previous send is still blocked, i.e. waiting for the send buffer to empty. If that's the case it discards the pending data to send. On the receive end it checks if the buffered audio is more than the desired latency, if it is, the buffer is discarded. That, along with the sample rate of 22050 makes it unsuitable for Bell202 modulation.

mfp20 commented 7 months ago

the buffer is discarded. That, along with the sample rate of 22050 makes it unsuitable for Bell202 modulation.

You mean the PCM sample rate? That can be configured in the c-sharp core audio libs, I suppose. In any case 22050 might be enough for some digital protocols, example: "It provides 8 kHz wide audio bandwidth while using just 1600 Hz of RF bandwidth" ( https://freedv.org/ )

But, yes, discarding ain't good enough to go digital...

ErikS-web commented 7 months ago

Interesting that you discuss QDNH technically 👍

Just to inform you: QDNH is also "functionally" described in the Online manual.