aspose file tools*
The moose likes Java in General and the fly likes Problem with code after first execution Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Problem with code after first execution" Watch "Problem with code after first execution" New topic
Author

Problem with code after first execution

Dave McNamara
Greenhorn

Joined: Feb 08, 2014
Posts: 12
Hi All,

Rather difficult question to ask but bare with me please. This is also my first post.
I have a setup which involves a Raspberry Pi, PC and Zigbee comms. Coding language i'm using is Java.

Ok, so my design involves my Pi taking a photo with the Pi camera and transmitting it to PC through zigbee comms.

My problem is when I run the code the first time, it works no problem and jpg image is transmitted and saved to PC. But when I go to execute the code again (without restarting the execution of the code) basically I want to be able to have the code running on the Pi indefinitely and let the PC send a signal at any moment in time to tell it to begin transmission.

So, I have an event handler on the Pi side in a method called connect() that if it receives a certain string it is to execute a method. There are 3 methods getImage,getSize and run. There strings are "" ":|" and "" respectively.

So PC sends "" to Pi which is in connect method until told otherwise, reads in string from port and triggers if loop for that string which for now is getImage. Then sends back a string "Image cropped successfully" which is read by the PC in a while loop, once it gets this string it then sends ":|" to the Pi to get the filesize. Once filesize is received at PC it then sends "" to begin transfer of image.

This all works fine and dandy for first execution, but on second execution the PC sends "" to getImage, does its stuff and Pi sends back "Image cropped successfully". The minute that is returned a random "" appears on the Pi side and begins to execute the getImage method again which in turn messes up the whole sequence of events.

The code for PC and Pi is attached, I'm relatively new to Java so please understand if my code is rough. Suggestions for improvement are welcome. Any help on this issue is appreciated as I have exhausted my debugging ideas. As you can see in code I have println thrown around alot to see the different steps.

Thanks
Dave

PI_SIDE_CODE



PC_SIDE_CODE

Jeanne Boyarsky
author & internet detective
Marshal

Joined: May 26, 2003
Posts: 30752
    
156

Dave,
Welcome to CodeRanch!

That's a lot of code which makes it difficult to provide comments on. One approach to troubleshooting is to create a SSCCE. Can you try making the code shorter/simpler to illustrate the problem? You may find the problem goes away in which case you put back that step and post here with the troublesome step. Or you may wind up with a small test example.


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12803
    
    5
Wild guess: I seem to recall some image handling problems related to not correctly disposing of system resources - see the java.awt.Graphics class dispose() method for example.

Is there some system resource involved here?

Bill
Dave McNamara
Greenhorn

Joined: Feb 08, 2014
Posts: 12
Hi guys,

Yes, sorry for the length of code posted, but at present i'm unsure of where the issue is. So its difficult to decide which piece of code is relevant. But saying that, there is only one area on the PC code side that has the "" string in order to write it to the port (below). That string is acknowledged on the Pi side and the assigned method is initiated.

I was thinking today, that it maybe the fact that I am using a thread in my GUI class to run the program, which at the moment I don't think is being closed after each transmission (should it be closed?). So possibly when the code runs again, it starts a new thread, so then 2 threads are running the same code at same time?

If so, how do I close the thread, there's warnings all over the internet about not using Thread.close(); or Thread.destroy();



My GUI method to start thread

William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12803
    
    5
If so, how do I close the thread, there's warnings all over the internet about not using Thread.close(); or Thread.destroy();


For good reason too! Why not let the thread end naturally by exiting the run method after cleaning up the connection?

Bill
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

On the Pi side of things, you have a ton of variables (lines 25 to 45) which are member variables, and which are not final. Similarly, on the PC side of things you have lines 9 through 29 all of which are member variable declarations. This sort of problem (where one time through the output looks correct, but the next time there is an exception or the wrong path is taken) is often caused by some state being left over between calls, and that is a sign that you are letting data escape the scope it should be in. A variable should be stored in the smallest scope possible, which is usually inside a method. It should only be moved to the instance scope if it absolutely necessary.

My suggestion would be to look at every variable you declare as a member variable and see if you can either move it into a method local scope or make it final. For example, in Piport you have public boolean wait. Where is that used? Does it make sense to have that flag last longer than a single method? Can you move it to the method which uses it? How about int BufferSize = 64; When is that value used? Does it ever change? Could you use private static final BUFFER_SIZE = 64; instead? The variables blockSize, bytesToRead, and bytesRemaining seem like they will be used in a particular IO loop to read bytes from the port, should they be member variables lasting the lifetime of the object or should they be member-local, only existing when you are actually reading from the port? This is probably most particular for the FileInput/OutputStreams, and the ack, size, input, sizeBuffer variables. You don't want any one of those things spilling from one request to the next. You should be ruthless with this stuff. Define no variables you don't need. If you need a variable in multiple methods, you should check to see if you can pass it as a parameter from one method to another, rather than storing it the instance scope. i.e. does it really need to last longer than a single call chain through the class. If Piport 'starts' from the connect() method, does the variable need to be used in connect() and one or more methods connect() calls (or those methods call)? Or does it need to exist between separate calls to connect() - and therefore multiple 'requests'? If the former, then you can take it out of the instance scope (member variable) and put it in the method scope and pass it as argument(s) to the methods that need it.

Don't forget to also check if the variable changes, if it does not, make it final.

Like I said, my guess is that you have some state which is being preserved from one execution cycle to the next. I can't see it in your code, but I didn't look at it too thoroughly (as others said, on the one hand there is too much of it but on the other hand it doesn't seem complete either). So treat the above as a hint as to where the problem might be and as a guideline that will help prevent this sort of thing happening in the future.


Steve
Dave McNamara
Greenhorn

Joined: Feb 08, 2014
Posts: 12
Hi Bill,

I tried letting the thread terminate end naturally by adding a return; statement, but it hasn't changed the outcome.

Hi Steve,

Thanks for the detailed post. Yes I have a lot of variables. A lot of which are not used anymore e.g public boolean wait; but never removed them, (my laziness and frustration) sorry. I have now moved around the these variables and declared in the appropriate methods.

If Piport 'starts' from the connect() method, does the variable need to be used in connect() and one or more methods connect() calls (or those methods call)? Or does it need to exist between separate calls to connect() - and therefore multiple 'requests'? If the former, then you can take it out of the instance scope (member variable) and put it in the method scope and pass it as argument(s) to the methods that need it.


Yes Piport begins in connect method and depending on incoming string the assigned method is called from there and then reverts back to connect method after file transfer has been successful by being called in the run method @



There is only one variable in connect method and that's String input; which is set to null each time connect(); is called and this variable is not used in any other method so I don't need to pass it?

For the problem I'm having (a repeated "" string). I cant see where it could possibly be preserved on either end of the transfer. But I do agree that it is probably whats causing it. I've single stepped through the code on the PC and used System.out.println(); all over the Pi code where "" could possibly be getting repeated, but with no success. I'm pretty stumped to be honest.

My plan is to be able to let this code run for 24 hours taking an image and saving to file each hour so I need it to be able to loop until I tell it otherwise.

Thanks for the input so far.

Dave

Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Don't forget to do the same in all your classes on both sides of the communication. And remember this applies to all resources, not just variables. I think you have timers and who knows what else. Make sure you aren't starting more than one timer (therefore firing the event more than once) or adding more than one action listener to your button which triggers the timer (thus triggering it more than once or creating more than one timer).

If you are having problems isolating which side the problem is coming from, remove one side. Stop using the PC side code and build a super simple GUI which has a button which does nothing but sends ":)". Then see if you trigger multiple reads on the Pi side of things when you press it multiple times. If it doesn't reproduce or you can't just send :) over and over again without breaking the Pi side, then make the PC side do the entire sequence one time:

Trigger that from a simple, single button GUI with no extras (no threads or timers or whatever...).

If the problem reproduces, it is on the Pi side. If not then reverse it. Install the initial PC side and replace the Pi side with something that does nothing but takes the request and sends back pre-defined responses and spits out logging. If the problem reproduces you know it is on the Client side.
Dave McNamara
Greenhorn

Joined: Feb 08, 2014
Posts: 12
Hi Steve,

Ya, that code you wrote is a lot neater than mine, thanks for that. much appreciated. Should make it easier to find the fault.

Apologies for delayed response, but currently where I live (Ireland) we are having very bad storms and electricity has been cut off, so I will hopefully get to run that code in the next day or 2 and see if I can find the fault.

I will let you know how I get on.

Regards,
Dave

Dave McNamara
Greenhorn

Joined: Feb 08, 2014
Posts: 12
Hi guys,

Okay after taking your advice Steve I took your code (thanks) and ran it on PC, due to its layout, it was A LOT easier to work with. Firstly just sending "" repeatedly and it worked no problem. Then ":|" (filesize) was introduced and it still worked ok.

When "" was introduced, it then started repeating. So my first assumption was that it was the run() method on the Pi side. So I created a new file (so at least i could go back to square one if ended up getting worse). Commented out connect();



And it didn't change the output, I then got rid of most of the code on the Pi side and just had it printing "", filesize of 1 and transmitting a small string. When this was executed, Strings displaying information that I had removed from the file were appearing. So this opened another can of worms. Spent a bit of time trying to figure that out, as the right file was being compiled and executed.

Took a break, came back and noticed in my main method:



although the file name and class name was changed (otherwise it wouldn't compile), the main method was still running the other file. So that was changed to the correct class and it then started to work.

The timers and threads were re-introduced and they now work and it's transmitting every 3 minutes.

Apart from the wrong file in "main" was being executed. The main issue in the Pi code was the connect(); in the run(); Commenting this out allowed for it to function correctly.

I'm not sure why, as I had assumed once the run(); method had finished, the program would need to start at connect() again hence call connect() at the end of the run() method. If anyone can clear that up i'd appreciate it

Again, thanks to all for you help, especially Steve
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Problem with code after first execution