Results 1 to 28 of 28

Thread: [RESOLVED] looking for guidelines for event driven vs thread

  1. #1

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Resolved [RESOLVED] looking for guidelines for event driven vs thread

    Guys
    I'm developing an app which requires access (and communication) between several arduino devices via both serial and also in ethernet. Consider it like a access controller machine, where you need to read ID card (via a COM port) and then you have to do the auth and then you will do some process. A little more on this is like:

    1) a vb.net app will be the front end for this
    2) an arduino is there for GPIO for actuator control and sensing (just 1 and 0 logic based sense)
    3) a smartcard reader
    4) A GSM module for SMS alert

    Now, the situation is a bit complicated. I can do some on-demand reading and also on-demand writing so far, with kindof a success. I have used timer based. Tick per 3 sec and this is actually making things a bit hard, uncomforting. So, here is the things again:

    1) the vb.net app on load, will open a form, named frmMain and will have several buttons for "OPEN" "Close" and some other admin works (like add new card, etc). This form will have also some labels for Status updating. So consider this frmMain as a UI frontend.

    2) The UI frontend (aka frmMain) is required to be updated on the GPIO status on a per second basis. So each change will be reflected nearly realtime. There will be some different polling too, like when GPIO is polling per second, GSM can poll per 2/3 sec. This will make the thing reasonable. ON no status update from GSM (send AT and reply OK) for a 30 sec, there will be a alarm generate, (aka, lableAlarm.backcolor=RED) Also on button press, the frmMain will send the arduino (or in some case, GSM) commands. [Please note: the keepalives will not come from arduino/gsm and we will send ping for a pong, and i am happy with that]

    3) The card reader reading job is a fully on demand basis, not a pollilng, on pressing the button, it will read smartcard for data, match it and then will allow to do the operation or else it will show a message on status label that card reading failure.

    Now, as you can see, some are on demand based and some are polling based, and all of them are sending data for frmMain's labels to be updated accordingly, I finally came out that I should go for threading (each job in a thread) and then each thread to update the frmMain.

    Now, all the examples i found in internet, they are having some wiered way of representation, Public class main() and so on... I dont know how to use them in frmMain and also, I'm a bit new in vb.net for specially threading and event baseed works. I worked in arduino (C++) where I have found it keeps looping and I can just call functions when I need. Here it's different.

    So I need a bit of a guidance on it... :

    1) is my threading thinking OK?
    2) how can I achieve it?? [reading say 2 com ports and an ethernet socket in three different thread and update the frmMain accordingly?

    Thanks in advanced!!!

    [Note: The application MUST run in smooth, not blocking codes!! (which is happening now)]

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: looking for guidelines for event driven vs thread

    For the on demand stuff, I wouldn't use threading unless I found that the time taken for the request and response was too much. I would expect it to be near instantaneous, in which case it might as well be on the UI thread.

    For the polling, threading makes more sense. One option is the BackGroundWorker component. The problem you will have to deal with in threading is that you can't update UI controls the way you would on the UI thread. They are thread specific, so attempting to update them from any other thread will give you an Illegal Cross Thread exception. This can be suppressed, but that is a very BAD thing to do. Threading has enough difficulties without adding more to them. The nice thing about the BackGroundWorker is that it has a ReportProgress event that it can raise whenever you want. That event is raised on the UI thread, so the event handler for it is on the UI thread and can freely update controls.

    However, a BackGroundWorker makes the most sense if you have only ONE thread running. I doubt there is a true rule about this, it just might get complicated with multiple BGW components. Besides, you talk about polling, and polling makes more sense using a timer. You are already familiar with the Windows.Forms.Timer. There are two others, but the one you want is (probably) this one:

    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx

    Here's a description and comparison of them:

    https://web.archive.org/web/20150329.../cc164015.aspx

    The Timers.Timer might also work for you, but the Threading.Timer seems the best, because you could just handle the poling in the tick event, which would occur on a different thread and wouldn't be directly impacted by the UI thread (well, mostly not, anyways, but if you have enough threads going, there could be contention, though you can likely ignore that). So, when the tick happens, you do your polling, then report the data out. There are a variety of ways you could do that. Just marshaling a call to access a control is likely good enough, but you could also queue the data into a Queue (of T) and post an event to the UI thread, which could pop the data off the queue as it gets around to it. That seems like overkill, though, since you make it sound like the UI form will just be sitting around waiting most of the time.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    hi, thanks for the reply...

    well, before going to discuss on your reply, let me inform you another issue...

    *) I know threading is tough and i used timer. Another form i made and that was loaded and kept visible=false for hidden and that was running per second. But I found running it for 5 sec interval is most flexible as then i can click on the buttons most easy way. But update comes later and I miss many info (I had to use readline() as i need to read the one line only, and surely the latest one for the most updated data). I know the last update but i miss many other updates in between. Also response seems a bit slow.

    *) When i used a per second based tick, then update is great!! But i cant even click any button at all, as it remains busy...

    I forgot to inform these two info too....

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: looking for guidelines for event driven vs thread

    Well, the per second based tick would have to be the polling, because nobody demands data every second. Anything that slows the UI is a fine candidate for threading. If once per second is causing the UI to be unresponsive, then a whole lot is happening every second. Since you are talking about COM, what is most likely happening is nothing at all. Most likely, you are just waiting for a response during the bulk of that time. That would be ideal for the thread, because it can wait without you even noticing.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    hang on!!! Did you just said, "Since you are talking about COM, what is most likely happening is nothing at all. Most likely, you are just waiting for a response during the bulk of that time. That would be ideal for the thread, because it can wait without you even noticing." ??

    Okey, So what I'm doing for polling is, I'm sending a "ping" to arduino for a reply. Arduino sends me reply when it gets a "ping"... This means it can be that after starting to listening, it will get the reply shortly right?? But what is my arduino is not responding, say down or something went wrong and no "pong" is coming after any "ping"... Because if i dont receive anything within 30 sec of a "ping" then i have to alert an alarm!!

    And in that case, I need an example of Serial port with thread (as most of the thing i found is saying public sub main() and i dont know what to do with that public sub main() when i have a private sub form1_load()...

    This new dot.net is a bit harder than my old vb6.0

  6. #6

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Hi,
    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx is the example that i used for making a elapsed time tick... things are nice... just got a cross thread violation when i tried to update a form's label

    in form2, this timer thread was running. I used Imports System.Timers... And then it's job was it will wait for 30 sec and then it will remove some data (flushing and removing the textbox data to initialize) in form1. And bam!! cross thread violation...

  7. #7
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    If you showed the code where you updated the textbox, we could give you specific code, but generally when I need to update something from a non-GUI thread I use a line like:
    Code:
       textbox1.Invoke(Sub() textbox1.Text = "Thread active")
    What the above does is generate an inline delegate and call it on the GUI thread to update the textbox, so the delegated code will always be done on the GUI thread regardless of what thread it is called from.

    The fact is you can call delegates from the GUI thread as well, and there are sometimes reasons to do that.
    Here is a simple example that calls the delegate from the GUI thread, first using Invoke, and secondly using BeginInvoke.
    Code:
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Static ctr As Integer
            ctr += 1
            TextBox1.Invoke(Sub() TextBox1.Text = ctr.ToString)
            ctr += 1
        End Sub
    Code:
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Static ctr As Integer
            ctr += 1
            TextBox1.BeginInvoke(Sub() TextBox1.Text = ctr.ToString)
            ctr += 1
        End Sub
    In the first case, the textbox will increase by 2 each time, but it will display the odd numbers.
    In the second case, the textbox will increase by 2 each time, but it will display the even numbers.

    The first case will cause the delegate to be run on the GUI thread when you invoke it, and then the code following the invoke call will run. That means if the invocation was called from another thread, that thread would be suspended until the delegate was processed on the GUI thread. Sometimes that is what you want, but other times not.

    The second case, BeginInvoke queues the delegate to be run on the GUI thread, but returns immediately so the code after the invocation call can run in parallel to the GUI thread. You may need to be aware of that if you are changing values that are referenced by the delegate as the value may be updated and not be equal to what it was at the time you passed it to the delegate.
    Such is the case in this example. Since we're invoking from the GUI thread, the delegate is queued but can't run until we give up the GUI thread by finishing our Sub. So, we increment the counter and exit the sub, freeing up the GUI thread, so now the delegate runs and updates the text of the textbox with the value of Ctr, which is now incremented by one compared to what it was at the time we did our BeginInvoke so the value will always be even, not odd (in this example).
    Last edited by passel; Jan 20th, 2018 at 10:29 AM.

  8. #8

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Okey,

    Here is a thread opened by me for the arduino part... the reason is explained there... and thus there is a big scope of changing the whole thing in a bit different way... [ref. arduino forum]

    Idea is: <1000101> this may change into something else or may not for a long time... So instead of polling, can I actually make it kind of event driven listening only, so when there is a change in that string, i will be reported (arduino will take care of reporting if there is a change... so who cares). And thus it will actually give me the kind of real time update (if there is change for a second, or seconds, i will come to know ofcourse) [Please let me know any arguments on it, i will welcome that].

    I am slowly turning into Serial or even ethernet... [currently though sticking with serial]. Also planning to keep the whole thing almost in the same from, frmMain. The most important thing is the system should run non blocking. [while polling, it gets hang... and also after a long time run, updates are not happening]

    There will be a keepalive involved with the vb.net and goip board, and on no response from goip board and pc (whoever found it offline) will raise an alert. Thus a keepalive of say 30sec is fine... and <1 is the keepalive bit actually... thus i can reset the keepalive timer on arrival of that bit.

    I will need the GSM only with Serial purely, as there is no other way... even whatever that is, but GSM is a kind of unpredictable for me... on detection network failure/sms incoming/jamming, vb.net MUST raise alert! Thus there is the pure vb.net to gsm polling requires also with event driven [as i found SMS incoming alert gets missed sometimes, which needs polling for pulling the SMS out, and event as if jamming occurs, then I have to still raise an Alert!]

    Options are possible here right??? Then some idea plz...
    Last edited by aq_mishu; Jan 20th, 2018 at 06:39 PM.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    OK guys!!

    Here is the update... I now am receiving the data via event handler, the way I actually wanted... any new data coming in from my arduino and it tells me. Exactly the way I wanted so far... This part though is a huge success, but still there is a huge stuck...

    As said, there are 2 devices... both running on serial and also i want to avoid timer based polling. I am more of focusing on event as to reduce data transmission. Now, arduino is fantastic. Because it sends a pre defined pttern text and i can just manipulate them as i need. but when it's a GSM modem, i can not... Say, if I send AT it sends me back <\n>OK [here \n means just a newline in console... not physically \n

    also when a new sms comes, it tells me this in console:
    Code:
    +CMTI=
    Now, I'm attaching most of the codes related here... because practically GSM is not coming out or not coming out properly.

    Code:
    Public Class FrmMain
    
        Private Delegate Sub UpdateFormDelegate()
        Private GPIOUpdateFormDelegate As UpdateFormDelegate
        Private GSMUpdateFormDelegate As UpdateFormDelegate
    
        'Dim thread As System.Threading.Thread
    
        Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            KeepAliveTimer.Enabled = False
            LoadConfig()
            RTC.Enabled = True
            LblStatus.Text = "Initializing..."
            'Me.CheckForIllegalCrossThreadCalls = False
            LblConfig.Text = "GSM port:" + globalConfig.GSMport + " GPIO Port:" + globalConfig.GPIOport 'for debug only.
    
            ConnectGSMSerial()
            InitGSM()
            GSMSerialPort.DiscardInBuffer()
            GSMSerialPort.Close()
            GSMSerialPort.Dispose()
            Thread.Sleep(3000)
            AddHandler GPIOSerialPort.DataReceived, AddressOf GPIOSerialPort_DataReceived
    
            ConnectGPIOSerial()
    
            InitGPIO()
            AddHandler GSMSerialPort.DataReceived, AddressOf GSMSerialPort_DataReceived
            ConnectGSMSerial()
            Thread.Sleep(50)
            'KeepAliveGSM()
            KeepAliveTimer.Enabled = True
    
    
        End Sub
        Private Sub GPIOSerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
            'Handles serial port data received events
            GPIOUpdateFormDelegate = New UpdateFormDelegate(AddressOf globalFunc.ProcessGPIOData)
            receivedGPIOData = globalConfig.GPIOSerialPort.ReadLine()
            Me.Invoke(GPIOUpdateFormDelegate) 'call the delegate
        End Sub
        Private Sub GSMSerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
            'Handles serial port data received events
            GSMUpdateFormDelegate = New UpdateFormDelegate(AddressOf globalFunc.ProcessGSMData)
            receivedGSMData = ""
            receivedGSMData = globalConfig.GSMSerialPort.ReadExisting() 'work in here
            Me.Invoke(GSMUpdateFormDelegate) 'call the delegate
        End Sub
    Code:
    Public Sub ConnectGPIOSerial()
            If (GPIOSerialPort.IsOpen) Then
                GPIOSerialPort.Close()
                GPIOSerialPort.Dispose()
            End If
            GPIOComPortSetup()
            Try
                GPIOSerialPort.Open()
                frmGPIODbg.lblConnStat.Text = "Connected"
            Catch ex As Exception
                GPIOSerialPort.Close()
                frmGPIODbg.lblConnStat.Text = "Disconnected"
                MessageBox.Show(ex.Message)
            End Try
        End Sub
    
        Public Sub ConnectGSMSerial()
            If (GSMSerialPort.IsOpen) Then
                GSMSerialPort.Close()
                GSMSerialPort.Dispose()
            End If
            GSMComPortSetup()
            Try
                GSMSerialPort.Open()
                frmGPIODbg.lblConnStat.Text = "Connected"
            Catch ex As Exception
                GSMSerialPort.Close()
                frmGPIODbg.lblConnStat.Text = "Disconnected"
                MessageBox.Show(ex.Message)
            End Try
        End Sub
        Public Sub InitGSM()
            Dim cmd As String
            cmd = "ATE0" + vbCrLf
            GSMSerialPort.Write(cmd)
            Thread.Sleep(5)
            cmd = "AT+CMGF=1" + vbCrLf
            GSMSerialPort.Write(cmd)
            Thread.Sleep(5)
            cmd = "AT+CLCC=1" + vbCrLf
            GSMSerialPort.Write(cmd)
            Thread.Sleep(5)
            cmd = "AT+SJDR = 1, 1, 255, 1" + vbCrLf
            GSMSerialPort.Write(cmd)
            Thread.Sleep(5)
            cmd = "AT+CMGD=1,4" + vbCrLf
            GSMSerialPort.Write(cmd)
            Thread.Sleep(5)
            'KeepAliveGSM()
        End Sub
        Public Sub InitGPIO()
            Dim cmd As String
            cmd = "0x00" '+ vbCrLf
            GPIOSerialPort.WriteLine(cmd)
            Thread.Sleep(5)
        End Sub
        Public Sub KeepAliveGPIO()
            Dim cmd As String
            FrmMain.LblIOCLink.BackColor = Color.Red
            cmd = "ping" '+ vbCrLf
            GPIOSerialPort.WriteLine(cmd)
            Thread.Sleep(5)
        End Sub
    
        Public Sub KeepAliveGSM()
            Dim cmd As String
            FrmMain.LblGSMLink.BackColor = Color.Red
            cmd = "AT" '+ vbCrLf
            GSMSerialPort.WriteLine(cmd)
            Thread.Sleep(5)
        End Sub
    
     Public Sub ProcessGSMData()
            Dim gsmData As String
            gsmData = Trim(receivedGSMData.Substring(0, 5))
            FrmMain.TxtOutput.Text &= CStr(gsmData) & vbCrLf 'For debug
            If gsmData Like "+CMTI=" Then
                'GSMisOK = True
                FrmMain.LblGSMLink.BackColor = Color.Green
            Else
                FrmMain.LblGSMLink.BackColor = Color.Red
            End If
        End Sub
    Any idea guys!! The GPIO is perfect!! GSM is not... and i need to react on receiving new sms incoming reporting and do the rest...

    Mishu~

  10. #10
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    Well, GSM is going to require more processing. The message isn't transmitted automatically, it is stored and you have to retrieve it.
    At the end of the "+CMTI=" string should be a position value that identifies the message received, i.e. what position in the message queue the message received is.
    You would then need to issue a command to read the message at that position, i.e. something like "AT+CMGR=<pos>".

    I'm not familiar with SMS processing myself, but in general you should be aware that using ReadExisting may not read the whole message because the time taken to transmit the message is much slower than the speed of the program, so usually you would be buffering the information read into a local buffer and building it up and parsing as needed. The GPIO is easier because the transmission is terminated by a new line, so the ReadLine will pause until the whole line is received so the synchronization is "built in". With ReadExisting, you'll need to be aware of the protocol of the data you're receiving so you can know when you've received the whole message, or some portion that is meaningful.

  11. #11

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Actually that is the issue... I know that Serial transport is a bit slow than the PC. Also readline is a kind of blocking architecture which helps me to read the whole line.... but as said, GSM module will send data either in a single line (not all time... ) which is fine for me... but when it will send data in several lines (like sms arrival, it send 2 lines) then I actually dont know how to read the whole thing... Andd thus looking for ideas...


    Another thing, I know that When I send AT, GSM sends me back <newline>OK [if i set for echo off] or AT<newline>OK [if i set echo on]. Now, how can I read this too??? (As there is a <newline> associated...

    Mishu~

  12. #12
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    If I understand the question, there are a couple ways I would expect the data to be processed.
    In one case, where I was interacting with a serial device, I would switch between ReadLine and ReadExisting depending on what responses I expected from the device.
    For instance, I might issue a command for information that I know will result in an unknown number of lines of text to be returned. But given that I know that it is sending lines, and I could recognize a pattern that would be in the final line transmitted, I would set a flag to use ReadLine to gather the text a line at a time. When I recognized the last line, I would clear the flag and return to reading using ReadExisting since the device would send a prompt, which wouldn't have a newline at the end.
    Likewise, I may issue a command that I know will return a prompt, so I will continue to use ReadExisting to gather the data to look for the prompt string since there would not be a newline at the end.

    The other expected option would be not to switch between ReadLine and ReadExisting but always use ReadExisting and look for the newline termination manually in the stream of data received, and when you see it send the collected substring off to be processed as a line. If the data returned doesn't have a newline termination, then you're not hung up waiting for it. You can either recognize the substring you've collected as an expected response, or perhaps assume if you didn't get any new data for a short period of time, that the sending of data is completed.

    The issue about not receiving new data for a short period of time means you need some way of detecting that, which means you either have to be using a polling paradigm so if you poll a number of times without getting new data you assume the data transmission is done, or you have some type of watchdog timer that implements a counter that can identify when you haven't received a DataReceived event for some period of time.

  13. #13

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Quote Originally Posted by passel View Post
    The other expected option would be not to switch between ReadLine and ReadExisting but always use ReadExisting and look for the newline termination manually in the stream of data received, and when you see it send the collected substring off to be processed as a line. If the data returned doesn't have a newline termination, then you're not hung up waiting for it. You can either recognize the substring you've collected as an expected response, or perhaps assume if you didn't get any new data for a short period of time, that the sending of data is completed.
    That's the thing... It always sends data in a line... either single line of multiple lines. I was ble to read the AT command response as only for AT.But not for others... So still the issue is not solved!!

    Yes!! Multi line reading with a flag for last line... I found a solution with a do loop for readline() where reading was untill NOTHING. so the flag here was NOTHING. I think NOTHING in vb.net is a CRLF right?? Because I have seen the thing is coming as CRLF (though I again need to be sure) some output CRLF another some output CRLF OK CRLF

    But the issue is sometimes I have seen at last double CRLF comes (though not a big deal). But then what is your suggestion on NOTHING???

  14. #14

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Guys,
    OK so here it is:
    I have sent AT+CMGL="ALL" and the return in console is coming like this:


    Code:
    <CR><LF>
    +CMGL: 1,"REC UNREAD","+0012345678912","","18/01/24,13:15:16+24"
    Test
    
    OK
    <CR><LF>
    Note: Each of the <CR><LF> is for sure a is a white spare [<CR><LF> is not printed, I added them here in the t/forum as else I think the code will be trimmed.

    So I need to parse it for the phone number and the sms body. But alas, I just cant read it at all. Also, I'm using event driven serial as that's kind of a requirement. Reason is, I will issue command if I need but my be, I need to detect new sms coming in, with the status indicator like

    Code:
    +CMTI: "SM",1
    which just pops up at all....

    My serial event codes are:

    Code:
    Private Sub GSMSerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
            'Handles serial port data received events
            GSMUpdateFormDelegate = New UpdateFormDelegate(AddressOf globalFunc.ProcessGSMData)
            'receivedGSMData = globalConfig.GSMSerialPort.ReadLine() 'work in here
            'receivedGSMData = ReceiveGSMSerialData()
            Do
                 Dim Incoming As String = globalConfig.GSMSerialPort.ReadLine()
                 If Incoming Is ("OK") Then
                      Exit Do
                 Else
                      receivedGSMData &= Incoming & vbCrLf
                 End If
            Loop
            Me.Invoke(GSMUpdateFormDelegate) 'call the delegate
        End Sub
    Code:
    Public Sub KeepAliveGSM()
            Dim cmd As String
            FrmMain.lblGSMLink.BackColor = Color.Red
            cmd = "AT" '+ vbCrLf
            cmd = "AT+CMGL=""ALL"""
            GSMSerialPort.WriteLine(cmd)
            Thread.Sleep(5)
        End Sub
    Code:
    Public Sub ProcessGSMData()
            Dim gsmData As String
            gsmData = receivedGSMData
            FrmMain.TextBox1.Text &= CStr(gsmData) & vbCrLf 'For debug
            If gsmData.Contains("OK") Then
                GSMisOK = True
            Else
                GSMisOK = False
            End If
            If gsmData.Contains("+CMTI: ""SM"",1") Then
                GSMisOK = True
                FrmMain.TextBox1.Text &= CStr("NEW SMS Detected") & vbCrLf 'For debug
            End If
    
            If GSMisOK = True Then
                FrmMain.lblGSMLink.BackColor = Color.Green
            Else
                FrmMain.lblGSMLink.BackColor = Color.Red
            End If
    first of all, i need to see the data in FrmMain.TextBox1.Text &= CStr(gsmData) & vbCrLf 'For debug here first. Bt I'm not getting anything at all....

    the KeepAliveGSM() fires on ever 10 sec via a timer.

    ideas??

  15. #15
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    I think you should set a breakpoints in sections of code that you are interested in and step through the code to see what it is doing.

    Since I don't work with GSM and SMS I can't really specifically help, but I would test a few things.
    For instance, you said it you use a terminal program and type in AT+CMGL="ALL" you get a particular return. If you send that command again, do you get the same response, or does it change because you have read the message, or does it filter things read. My assumption you would get the same response but with possibly a change indicating the message has been read.

    If you just send an "AT" command (without the crlf at the end since you're using writeline), you would expect to be receiving "OK" back so I would start with that to verify your commands are being sent, and your ProcessGSMData sub is being triggered and processing the way you expect.
    For instance, it doesn't seem to make sense that you are checking for "OK" (If gsmData.Contains("OK")) in your ProcessGSMData sub, since you filter out the "OK" string in your GSMSerialPort_DataReceived sub (i.e. you exit the loop and don't add the "OK" to the receivedGSMData string.

    If you set breakpoints and step through the code it would allow you to verify that the code is doing what you expect. That is the simplest and quickest way to debug code.

  16. #16

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Strange, I used this: receivedGSMData = globalConfig.GSMSerialPort.ReadExisting()

    and updated my [B]processGSMData()[\B] into [B]FrmMain.TextBox1.Text &= CStr(gsmData)[\B] earlier there was a vbcrlf at the end.

    Now the textbox1 shows:

    Code:
    +CMGL: 1,"RECREAD","+0123456789","","18/01/25,11:54:54+24"
    Test
    
    OK
    When I send a AT+CMGL="ALL" as a command. Now, I will do the polling on each 10 sec as usual. This result may not be always equal. First of all, the [B]"18/01/25,11:54:54+24"[\B] will have a chance to be changed as different time and date. Caller ID will be same in size, but number may be change. The next line is the SMS content that will be changed ofcourse...

    So, is there anny way to parse them?? This particular format?? Probably removing all of the vbcrlf and making it into one single string... so that i can manipulate using substring...

  17. #17
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    I wouldn't remove the line endings myself, but I guess it depends on what you are trying to parse.
    You can access each line of text in the textbox by using the Lines array of the textbox.
    You can split the string into a string array of "fields" by splitting on the "," for the lines you're interested in.
    An example
    Code:
        Dim sa() As String   'an empty string array
        For Each s As String In TextBox1.Lines  'for each string in the Lines array
          If s.Contains("CMGL") Then
            sa = Split(s, ",")
            Debug.Print(sa(2)) 'print phone number
          End If
        Next

  18. #18

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    OK, now, I have found a PDU (protocol Data Unit) decoder for SMS. It's an API. So I can use it... to retrieve the data...

    all I need is to read these in to a single string... from the serial.readexisting or readline...

    the output for the command "AT+CMGL=4" will give this:

    Code:
    <CR><LF>+CMGL: 1,0,"",25<CR><LF>0891881007000016F6040D91881018137009F500008110521203224205D4F29C0E02<CR><LF><CR><LF>OK<CR><LF>
    The <CR><LF> i made after reading, by replace() function. So, step by step:

    When the form will load, the timer will fire(r on demand) the command: "AT+CMGL=4" and then vb requires to listen for event of serial receive.

    Then, when there is a data, for single line or for multiline, i need to read it... (single line data will not practically come with any "OK" [no notification comes with OK i found, but command response comes with OK or ERROR]. but in most multiline data, there is a <CR><LF>OK type of thing. I dont need that OK at all... so i need to read and construct the whole string into a single string Here I need your help exclusively

    Once I have a variable holding the whole string of the output like:
    Code:
    <CR><LF>+CMGL: 1,0,"",25<CR><LF>0891881007000016F6040D91881017133009F500008110521203224205D4F29C0E02<CR><LF><CR><LF>
    I can strip it to make the thing like
    Code:
    0891881007000016F6040D91881017133009F500008110521203224205D4F29C0E02
    and then can use the API. So I really need the assistance as it's like i'm totally stuck in here...

    I prefer to avoid any textbox to hold the data, and i am using this text box only for debugging during development

  19. #19
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    Once you have a variable holding the whole string, split it on the LF character into an array of strings (use previous example as an example of using split).
    The string you want should be in the second element of the array, with possibly a <CR> on the end.
    If you use the trim function, it should strip off the <CR> character or you could use substring to drop the last character when you access it.
    Then use that string with your API.

  20. #20

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    OK, last night I did it, but with not that good luck... lately I had to put it in a textbox just because i had to avoid the error message... so here I'm again giving the whole thing:

    Code:
    Private Sub GSMSerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
            receivedGSMData = ""
            'Handles serial port data received events
            GSMUpdateFormDelegate = New UpdateFormDelegate(AddressOf globalFunc.constructGSMData)
            receivedGSMData = globalConfig.GSMSerialPort.ReadLine() 'work in here
            Me.Invoke(GSMUpdateFormDelegate) 'call the delegate
        End Sub
    Then,
    Code:
    Public Sub constructGSMData()
            Dim gsmData As String
            gsmData = (receivedGSMData)
            gsmData = gsmData.Replace(vbCrLf, "<CR><LF>")
            'FrmMain.TextBox1.Text = FrmMain.TextBox1.Text.Insert(0, CStr(gsmData) & vbCrLf) //changed it
            gsmResultStr = gsmResultStr.Insert(0, gsmData & vbCrLf)
            processGSMData()
        End Sub
    Then:
    Code:
    Public Sub processGSMData()
            Dim gsmData As String
            'gsmData = Trim(FrmMain.TextBox1.Text)
            gsmData = gsmResultStr
            FrmMain.TxtOutput.Text &= gsmData 'debug
    
            If gsmData.StartsWith("OK") Then
                GSMisOK = True
                Dim datalength As Integer = gsmData.Length
                If datalength > 8 Then
                    MsgBox("more message available", vbOKOnly) 'debug
                    gsmData = gsmData.Remove(0, 8)
                    Dim gsmDataLines() As String = gsmData.Split(vbCrLf)
                    MsgBox("gsmData:" & gsmData, vbOKOnly) 'debug
                    MsgBox("newString0:" & gsmDataLines(0), vbOKOnly) 'debug
                    MsgBox("newString2:" & gsmDataLines(2).Remove(0, 1), vbOKOnly) 'debug
                    smsRxPDUstring = gsmDataLines(0)
                    If smsRxPDUstring.Length > 10 Then
    
                    End If
                    receivedATresponse = gsmDataLines(2).Remove(0, 1)
    
                    If receivedATresponse.StartsWith("+CMGL:") Then '+CMGL is a new SMS
                        FrmMain.TextBox1.Text = ""
                        Dim cmd As String = "AT+CMGD=1,4"
                        GSMSerialPort.WriteLine(cmd)
                        Thread.Sleep(50)
                        newSMS = False
                        MsgBox("SMS Deleted", vbOKOnly) 'debug
                    End If
    
                End If
                MsgBox("datalength:" & datalength, vbOKOnly) 'debug
            End If
    
            If gsmData.StartsWith("+CMTI:") Then
                GSMisOK = True
                FrmMain.TxtOutput.Text &= "New SMS Arrived" & vbCrLf 'debug
                KeepAliveGSM()
            End If
    
            If GSMisOK = True Then
                FrmMain.lblGSMLink.BackColor = Color.Green
            Else
                FrmMain.lblGSMLink.BackColor = Color.Red
            End If
        End Sub

    then it gives an error: System.NullReferenceException: 'Object reference not set to an instance of an object.'
    at gsmResultStr = gsmResultStr.Insert(0, gsmData & vbCrLf) when there is a new sms comes...

    Thus i lately put everything in a text box and reading from there... (which i dont like and dont think a good way...).

    I want to put the new data at the starting as I know, OK will come at last, as a flag for command successful. And then the data, and then the command's flag, what type of command it is...

    [there are some special cases, but i want to discuss later on special cases...]

    ideas??

  21. #21
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,296

    Re: looking for guidelines for event driven vs thread

    That means that gsmResultStr is Nothing when that line is executed. Where did you expect a value to be assigned to it? I don't any likely candidates.

  22. #22
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    As jmcihinney says, you're using gsmResultStr on the right side of the assignment "gsmResultStr.Insert(..." but that assumes gsmResultStr already references a string you want to insert to.
    I would expect at some point before you start processing (perhaps at the beginning of your keep alive tick) you want to initialize gsmResultStr to an empty string, i.e.
    gsmResultStr = ""
    so now gsmResultStr references a string that you can insert into, although I'm not sure why if this code was building up gsmResultStr it would want to insert at the beginning of the string as that would assembling the string in backward chunks.

    Perhaps you just need to append gsmData & vbCrLf to gsmResultStr, rather than insert (you would still need to initialize gsmResltStr to an empty string first I would assume) or perhaps you just need to assign gsmData & vbCrLf to gsmResultStr if gsmData is the complete transmission at that point, i.e.
    gsmResultStr = gsmData & vbCrLf
    which means gsmResultStr would not have to be initialized to an empty string at the start because you are assigning a string to it at this point and the initialized empty string would be discarded anyway.

  23. #23

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Quote Originally Posted by passel View Post
    I'm not sure why if this code was building up gsmResultStr it would want to insert at the beginning of the string as that would assembling the string in backward chunks.
    the reason is always on any successful transmission, there will b a "OK" or "OK<CR><LF>" come. Thus if I can see there is an OK, (regardless of position) then i can put the system to go further for parsing. Else why t do the parsing?

    Because keepalive always wish to see a OK. So keepalive will actually look for any new sms and if there is, then 2 in 1, a OK and also then parse the sms. else do nothing. And yes, hen there is a notification, then also based on notification string, do what needs to be done. I could have done this also the other way i think... But when i was developing the whole thing, i never thought of decoding PDU data.

    Now, about the putting in a variable, let me see it... spent a whole night (like many) again on studying a protocol doc and now dizzy!!

    I think you are right, i need init the variable first...

    (problem is i have to work in C++ for arduino and vb for the app, and things are getting complex...)

  24. #24

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    OK, guys, so far the variable method is working.... I just had to initialize it at loading and also during the keepalive cycle...

    just a bit worried on one thing, say i haven't done keepalive yet, and here is a new sms came... what will happen? [it should work as init has done during load]

    another confusion is, say one sms already came, and then the second sms too... but keepalive not fired yet... then what may happen?? [infact that is another reason of going it backwards, insert method, as always the first line is the newest line... and i dont know what will be the last line ]

  25. #25
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,296

    Re: looking for guidelines for event driven vs thread

    This line:
    vb.net Code:
    1. gsmResultStr = gsmResultStr.Insert(0, gsmData & vbCrLf)
    doesn't really make sense anyway. Why use Insert at all when what you actually want to do is join two Strings together? If you do this:
    vb.net Code:
    1. gsmResultStr = gsmData & vbCrLf & gsmResultStr
    then you get the same result without danger of a NullReferenceException because concatenating Nothing is the same as concatenating an empty String.

    Also, while it's not essential, it's generally considered proper to use Environment.NewLine to represent a line break.

  26. #26
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: looking for guidelines for event driven vs thread

    Quote Originally Posted by aq_mishu View Post
    ... say one sms already came, and then the second sms too... but keepalive not fired yet... then what may happen?? [infact that is another reason of going it backwards, insert method, as always the first line is the newest line... and i dont know what will be the last line ]
    Well, you're the one reading the protocols, and it seems you could send yourself messages to test various scenarios.
    I don't know that a keepalive is even necessary. It seems what your doing a keepalive is merely a poll to pull all the messages from the message queue/list. It doesn't seem like the correct way to go about it.

    Based on what you've said in this post, it seems like whenever a new SMS message is received the message is stored in an indexed list. After it is stored then a protocol message is sent from the modem over the serial line telling you the index of the just received message, e.g. "+CMTI=5" or "+CMTI=6", etc... indicating that you've received a message and at what index the message was stored.
    It seems to me, that when you receive the +CMTI=<pos> message, you would then issue the AT+CMGL=<pos> to retrieve that particular message.
    Your issuing AT+CMGL="ALL" periodically seems like it will just return all the messages in the list every time you send the command and that doesn't strike me as being necessary or correct.

    Again this is based on what you've said in this post, and what seems logical about how the messaging protocol might work based on what you've posted.
    I think if I wanted to experiment with different scenarios, I would put the "keepalive" code in a button event rather than a timer so I can control when it is sent out. I would then send messages and monitor the responses from the modem before and after I "poll" by pressing the button. I would test the case of sending several messages before doing a poll.

    I think when you first start the program, there might be a reason to poll the modem to get a list of the messages that may be stored, but after that you would wait to be triggered by a "CMTI" message from the modem before doing any other reading, and only reading the particular message received. (assuming I'm correct in how the protocol and mechanism of the SMS messaging through the GSM modem (is that redundant) works)

  27. #27

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Guys, definitely both of you are right... but i am doing this way as I always need the latest sms first under any condition... and i dont need to read what is in air or or in memory, as this is a device that will be ON for years.

    [and there i need to open another thread may be, for running it extended time in desktop, how and what to...]

  28. #28

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: looking for guidelines for event driven vs thread

    Guys,

    I thank to all of you for guiding me all through here. Upto here, I'm concluding the topic, as so far it's working fine for last 48 hrs. I hope, it will run perfect for months too.

    And hence, I'm closing this chapter here, and surely i will come back (i hope i will never have to) to you with any issues and help i may need in regards of this topic.

    Thanks again for everything!

    Mishu~

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width