Recent

Author Topic: Solved: Thread with CLI  (Read 657 times)

ojz0r

  • New Member
  • *
  • Posts: 21
Solved: Thread with CLI
« on: January 21, 2021, 09:37:03 am »
Hello, first post from me.

I'm creating an application with a loop to manipulate hardware I/O on a Raspberry Pi Zero (single core).
The main loop is running with a delay/sleep at the end to create a fixed cycle time.
I would like to create a CLI (command line interface) to be able to communicate with the program i made.
So i implemented a readln(command) and then use a case statement loop to output information with writeln(..) to correspond to the input command.
If i was to implement the readln in the main loop it would block the cycle until a command is entered, this is not good since i want the main loop running all the time.
So i started looking at threads. I implemented the readln and case in a procedure/function and started a beginThread to run it in parallell. It kinda works but the result is not really what i expected. The main loops keep going so thats good, but the writeln output from the CLI function is offset on every line on the command line and there is no echo back on the keystrokes like a normal readln do but it seems to register because the first command followed by enter outputs, but subsequent inputs require multiple enters before it registers the command, also first new keystrokes seems to register as enter for some reason. (Its a little hard to explain in detail)

I have tried looking for a solution to this and ive read alot of documentation and forums but nothing seems to correspond to this type of case.
This is a hobby project btw.

(My background in Pascal is two weeks  ::) allthough i have a background in electrical and automation engineering with programming in Structured Text that is losely based on Pascal which lowered the bar. I also have experience in Verilog programming of FPGA/CPLD's.)

Edit: Changed title to solved.
« Last Edit: January 21, 2021, 08:50:22 pm by ojz0r »
Just trying to learn.

MarkMLl

  • Hero Member
  • *****
  • Posts: 2427
Re: Thread with CLI
« Reply #1 on: January 21, 2021, 10:24:44 am »
I sympathise. This isn't something which is easy, and most people who attack this sort of thing are doing so to "write a better shell"- which they often call a terminal emulator, which is really something completely different. From what you say, you're trying to produce something like AutoCAD's classic user interface, i.e. a line at the bottom of the screen into which you can enter commands to supplement the menus at the top of the screen.

Now, there's a number of things you haven't told us and if you weren't an admitted beginner you'd be kicked for it. You've not explicitly said anything about your target system but it's quite obviously some variant of Linux. You've not said what version of FPC you're using, ditto Lazarus if you're using it as the development environment. Possibly most importantly, you've not said whether this is a program running in the context of a shell session of if it's GUI based, and leading on from that where exactly you expect the program to display its output and get its input (i.e. in the shell window, or in a pane of a GUI program).

Normally we'd say "Post your code!" with the implicit promise that we wouldn't be too destructively critical. But I suggest that at the very least you satrt off by addressing some of the questions above.

Apart from that somebody might be along shortly to say "of course this is easy, all you have to do is use /this/ component"... but I'm afraid that won't be me.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

ojz0r

  • New Member
  • *
  • Posts: 21
Re: Thread with CLI
« Reply #2 on: January 21, 2021, 11:17:24 am »
Thank you for the response MarkMLl.
Sorry for all the confusions - i will try to answer your questions. (My code would probably be almost unreadable and break alot of conventions for experienced programmers)

What i want is this (simplified):
Code: Pascal  [Select][+][-]
  1. var
  2.         Stop: boolean = FALSE;
  3.         command: string = '';
  4.  
  5. while not Stop do
  6. begin
  7.         writeLn('Enter command, type help for help');
  8.         readln(command);
  9.  
  10.         case command of
  11.                 'help':
  12.                 begin
  13.                         writeLn('Enter terminate to terminate');
  14.                         writeLn('Enter asdf for asdf');
  15.                         writeLn('Enter help for this help');
  16.                 end;
  17.  
  18.                 'terminate':
  19.                 begin
  20.                         Stop := TRUE;
  21.                 end;
  22.  
  23.                 'asdf':
  24.                 begin
  25.                         writeLn('asdf');
  26.                 end;
  27.                 else
  28.                         writeLn('Unknown command');
  29.         end; (* end case *)
  30. end; (* end while *)
  31.  

I want to run this kind of routine in parallell with with a main loop that handles other silent executions without writeLn/readLn.
No GUI or anything i just start the compiled program with ./<program> from the Linux terminal shell so all writeLn/readLn is purely text based in the shell.

Im coding in plain text (nano in linux/code editor on android, i know i like to tourture myself) and then SSH into my Raspberry Pi Zero running Raspbian Buster (10) which is the target system and compile it with FPC <program.pas>. FPC is version 3.0.4 for ARM.

I hope this helps a little on the way to start.
Just trying to learn.

MarkMLl

  • Hero Member
  • *****
  • Posts: 2427
Re: Thread with CLI
« Reply #3 on: January 21, 2021, 12:02:47 pm »
If it's entirely command-line stuff (i.e. no GUI) it's easier. I'd suggest that you're doing it the wrong way round, and that you'd be better off using the main thread for your user interaction and a secondary one for the background stuff, without a GUI you should be able to use normal programming techniques in both (if you were using a GUI, you'd not have direct control of the GUI from the background thread).

I suggest having a tinker with it yourself and then posting your COMPLETE program here. We're all of us doing other things and really don't appreciate having to invent wrapper code, we won't start kicking you for bad code until you've got enough experience to know better :-)

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1393
  • Former Delphi 1-7, 10.2 User
Re: Thread with CLI
« Reply #4 on: January 21, 2021, 12:07:22 pm »
You've not explicitly said anything about your target system but it's quite obviously some variant of Linux.

Eh? I run FreeBSD on my Pi (I believe all of the *BSD family run on it). Not so obvious ;)
Lazarus 2.1 r65019 FPC 3.3.1 r49223 macOS 10.14.6 Xcode 11.3.1
Lazarus 2.1 r65019 FPC 3.3.1 r49223 macOS 11.2.3 aarch64 Xcode 12.4
Lazarus 2.1 r61574 FPC 3.3.1 r42318 FreeBSD 12.1 amd64 VMware VM
Lazarus 2.1 r61574 FPC 3.0.4 Ubuntu 20.04 Parallels VM
Lazarus 2.0.10 FPC 3.2.0 Win10 Parallels VM

kupferstecher

  • Sr. Member
  • ****
  • Posts: 426
Re: Thread with CLI
« Reply #5 on: January 21, 2021, 12:08:53 pm »
Hello ojz0r, welcome to the forum!

I implemented the readln and case in a procedure/function and started a beginThread to run it in parallell. It kinda works but the result is not really what i expected.
As far as I know, you have to perform all Console operations from within the main thread, otherwise strange things will happen, including application crashes. The same holds for all GUI elements.
There are synchronization technics* like "Synchronize" or using messages to communicate between a thread and the main thread. But as your read-commands are blocking, this doesn't help here.

So I think there is no simple solution for that problem. You could just put a console-like graphic control into your GUI application, but I don't know if there are existing ones with read capability.


*You probably already know that page:
https://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial

MarkMLl

  • Hero Member
  • *****
  • Posts: 2427
Re: Thread with CLI
« Reply #6 on: January 21, 2021, 12:43:33 pm »
As far as I know, you have to perform all Console operations from within the main thread, otherwise strange things will happen, including application crashes. The same holds for all GUI elements.
...
*You probably already know that page:
https://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial

That's not really true for a non-GUI program. By and large input and output are simply standard handles, and they're thread-safe.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 2427
Re: Thread with CLI
« Reply #7 on: January 21, 2021, 12:44:37 pm »
You've not explicitly said anything about your target system but it's quite obviously some variant of Linux.

Eh? I run FreeBSD on my Pi (I believe all of the *BSD family run on it). Not so obvious ;)

Yes Trev but you're... where did you say you were again? :-) :-) :-)

However I think the important point is that he's probably not running some variant of Windows. And even less likely to be running RISCOS or anything /really/ exotic :-) So by and large he's working with the fairly standard unix APIs.

MarkMLl
« Last Edit: January 21, 2021, 12:46:36 pm by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 2918
  • Compiler Developer
Re: Thread with CLI
« Reply #8 on: January 21, 2021, 02:03:52 pm »
However I think the important point is that he's probably not running some variant of Windows.

Which is possible however (I have a Pi with Windows IoT Core).

And even less likely to be running RISCOS or anything /really/ exotic :-)

They do provide Pi compatible images however... but then ojz0r would have come here with a different question, cause FPC does not support RISCOS yet. ;)

MarkMLl

  • Hero Member
  • *****
  • Posts: 2427
Re: Thread with CLI
« Reply #9 on: January 21, 2021, 02:45:39 pm »
On the balance of probabilities, yer honour... :-)

In any event, I don't think the OS matters that much unless OP gets to the stage of checking whether stdin has been redirected... and perhaps not even then. The worst I anticipate is that if he has really obscure requirements he might need to do a character-by-character read so he can apply a timeout, but since he's already talking about splitting things into threads that's unlikely.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

ojz0r

  • New Member
  • *
  • Posts: 21
Re: Solved: Thread with CLI
« Reply #10 on: January 21, 2021, 08:54:29 pm »
Than you all for the help!

I shuffled everything around to have the "CLI" part in the main loop while spinning off the old main loop (with actual logic) in a separate thread and after a little trial and error i got it working as inteded.
Allthough i had to use a loop with KeyPressed detection from crt to prevent the readln from blocking the interfaces with my units.

Now ill just have to clean everything up  %)
Just trying to learn.

 

TinyPortal © 2005-2018