Author Topic: updating parameters via the HTTP  (Read 15821 times)

Offline twoerner

  • Newbie
  • *
  • Posts: 16
    • View Profile
updating parameters via the HTTP
« on: July 18, 2007, 06:59:52 PM »
Hi Mark,

I have a minimal HTML page to allow a user to change the device's IP/netmask. My understanding (and this seems to work) is that after changing the, say, IP address in the <input> box the user then needs to

a) click on some button which will cause an "I" variable to have the value of the new IP address (e.g. Ii=192.168.0.4) and an "es" command which causes the values to be saved temporarily and cause a reset to occur
b) once back up the user has 3 minutes to issue an "em" command to validate the settings
c) then click again to issue an "es" command

I would like to be able to do 2 things:
1) have just one button which is smart enough to either say "save" or "verify" based on which state it is in
2) only have to do steps 'a' and 'b' above, in other words I think it would be nice if it were only a 2-step process to change the device's IP address

Does this sound possible? I can post snippets of code if you need a better idea of how I've been modifying things.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: updating parameters via the HTTP
« Reply #1 on: July 18, 2007, 08:21:47 PM »
Hi

Yes it does work more or less like that - but the step c is already not necessary. The ideas is to ensure that the user doesn't set something incorrectly and leave a device (possibly on the other side of the world) in a state where it can no longer communicate. Therefore the settings are only permenantly saved after the new settings have been validated, through real use. Since the new settings are loaded after the reset, it is only necessary to perform step b to accept and save them. c is not necessary.

However step a is actually composed of 2 actions. First modify the value (which is displayed as modified) or modify several values. All changes can be reversed by clicking on "Reset changes". When saving them, the reset is initiated (after a short delay to allows the page to be first refreshed).

It is possible of course to change and immediately save to FLASH (parameter system) or save one of the steps but I think that the present solution is not a bad general one.


It is very easy to change the text on a button or change its meaning (although the code can usually easily interpret a single command based on its present state without actually changing the command a button sends).

The present LAN setting HTTP file contains the following:

Code: [Select]
<input type=submit value="Modify / validate settings" name=em>
The button is always displayed as Modify / validate settings

If you change this to
Code: [Select]
<input type=submit value="£vM1 settings" name=em>(example. £v = insert value / string, Modify type 1 - I am assuming that M is not already used)

Your fnInsertString() routine in webInterface.c can handle the case 'M' (and '1' if there are more than one such query) and insert either "Modify" or "Validate" depending on whether it is waiting for validation or not.

You will find a call fnAreWeValidating() which will decide which to do.

Therefore this code will do the trick:


Code: [Select]
static const CHAR cValidate[]  = "Validate";
static const CHAR cModify[]  = "Modify";

case 'M':
if (fnAreWeValidating() != 0) {
/* uStrcpy(&cValue[(sizeof(cValidate) - 1)], cValidate);
   *usLengthToSend = (sizeof(cValidate) - 1) + (sizeof(cValidate) - 1); corrected 21.7.2007!! */
    uStrcpy(cValue, cValidate);
   *usLengthToSend = (sizeof(cValidate) - 1);
}
else {
/*  uStrcpy(&cValue[(sizeof(cModify) - 1)], cModify);
   *usLengthToSend = (sizeof(cModify) - 1) + (sizeof(cModify) - 1); corrected 21.7.2007!! */
    uStrcpy(cValue, cModify);
   *usLengthToSend = (sizeof(cModify) - 1);
}
break;

This technique is very simple but can be used for quite interesting effects. It can for example change colours (see the I/O page where the state of outputs is displyed by setting an appropriate colour).
Or different graphics (jpg etc.) links can be loaded depending on certain states.
Or by modifying a meta tag, the page can be caused to refresh it self at a user definable interval (or disabled), or other links can be jumped to after a small delay depending on variables and states, etc.
State depending java scripts could be loaded...
...In fact the list of examples could go on and on...

Therefore once you have learned how to use this you should find that you have the flexibility to do most things that you need without much complication.

Good luck

Regards

Mark
« Last Edit: July 20, 2007, 11:38:26 PM by mark »

Offline twoerner

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: updating parameters via the HTTP
« Reply #2 on: July 18, 2007, 10:38:30 PM »
Your suggestions are awesome... and so quick! I guess what I needed most was to look at fnInsertString and that I needed the £v operation.

Just a couple quick notes...
1) Operation 'M' is already taken (for MAC display) so I used 't' which appears to be unused so far.
2) I'm not sure your code example as given would work, it looked more complicated than it needs to be. But the following works fine for me:

Code: [Select]
        // save/verify button when updating network params
        case 't':
                    if (fnAreWeValidating()) {
                            uStrcpy (cValue, "Validate");
                            *usLengthToSend = 8;
                    }
                    else {
                            uStrcpy (cValue, "Save");
                            *usLengthToSend = 4;
                    }
                    break;

with an HTML page of:

Code: [Select]
<input type=submit value=£vt1 name=em>

Now here is where I'm getting confused. I have been modifying a fair amount of the uTasker code so there's always the possibility that I've modified a couple things too many and have somehow lost the functionality you've programmed. But with the code that I have:

1) I load the page from address 192.168.0.3, it shows 192.168.0.3 as its IP address and the "Save" button label is active
2) modify the IP address to 192.168.0.4, click "Save"
3) because we're sending the "em" command no reset occurs
4) the button label never moves into "verify" mode
5) I can open a new browser window, but at address 192.168.0.3, and I see the IP address value of 192.168.0.4
6) if I reboot the board it shows up at 192.168.0.3, and the IP value is 192.168.0.3

So no change has taken place and I can't verify the change.

So I modified the code to look like:
Code: [Select]
        // save/verify button when updating network params
        case 't':
            switch (*ptrBuffer) {
                    case '1':
                            if (fnAreWeValidating()) {
                                    uStrcpy (cValue, "Validate");
                                    *usLengthToSend = 8;
                            }
                            else {
                                    uStrcpy (cValue, "Save");
                                    *usLengthToSend = 4;
                            }
                            break;

                    case '2':
                            if (fnAreWeValidating()) {
                                    uStrcpy (cValue, "em");
                                    *usLengthToSend = 2;
                            }
                            else {
                                    uStrcpy (cValue, "es");
                                    *usLengthToSend = 2;
                            }
                            break;

                    default:
                            uStrcpy (cValue, "??");
                            *usLengthToSend = 2;
                            break;
            }
            break;

and use a web page of:

Code: [Select]
<input type=submit value=£vt1 name=£vt2>

So that the web page switches between "es" and "em". Using this code:

1) I load the page at 192.168.0.3, it shows 192.168.0.3 and a "Save" button
2) I change the IP address to 192.168.0.4 and click "Save", the "es" command is sent
3) the board resets
4) after reset I log into the board at address 192.168.0.4, the button label shows "Validate" and the board's IP address is reported at 192.168.0.4
5) I click "Validate", the "em" command is sent
6) the IP address field is editable again

Now, here's where my confusion is at this point, if I press RESET or power-cycle the board, after it comes up it is still at 192.168.0.4 (i.e. the new IP address) however, the IP field is not editable and the button label shows "Validate". I can keep clicking on "Validate" and power-cycling all I want, every time the board comes back up the values still need to be validated. I now need to issue one more "es" command. Only after I perform one more "es" command can I power-cycle and have the board be at IP address 192.168.0.4, show that IP address in the address field, have the IP address editable, and the button label read "Save".

In other words it seems like I have to perform an
1) "es"
2) "em"
3) "es"
command sequence to change the IP address and have it survive a power-cycle or reset.

Is there a way to short-circuit this sequence so that, say, after the second command (the validate or "em") I can power-cycle and have the IP address saved? I guess I could just edit the code to perform the "es" block after a "em" block. Is this how you intended the code to work?

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: updating parameters via the HTTP
« Reply #3 on: July 18, 2007, 11:30:59 PM »
Hi

Our codes are in fact equivalent.

uStrcpy (cValue, "Validate");
*usLengthToSend = 8;
is simply a bit riskier.

"Validate" is in fact a pointer to CHAR x[] = "Validate";
and (sizeof(x)-1) is 8.
The risk is that if you were to type in the length incorrectly - eg. 7 it would't be exactly correct and if you once edit the string and forget to change the length correctly it will also fail (slightly). Using the method which I use you can modify the string as you want without any risk of the code being broked.

[note that the insert string handling is performed in a case so there is no risk of chosing something which is already taken - it throws a compiler error and then simply try the next...]

To the sequence of changing and saving; I think that it is all working as I expect it to work after your modifications. I think that there are just some details about when things are changed in the temporary parameter buffer, when they are saved to FLASH in a the swap buffer, when the are validated in FLASH and when the program thinks that they are validated which is not exactly as you are expecting it to be.

I must admit that it is a bit complicated but the demo code is an example of how it could all be handled in a real project (because the demo is in fact also a real project...).
I think the things to be noted are:

1. The state validating is exists after a reset. It is only actually checked when loading the parameters from FLASH after a reset so just be changing (event saving to FLASH) you will never get the validating state which you are expecting - it needs the reset (unless you edit the state flag yourself;-)   ).

2. When parameters are modified they are modified in RAM. There are two copies - a temporary version and a working version. Some modifications are made in the working version and so are immediately valid (eg. changing serial port speed - this is done on the fly). Some are changed in the temporary buffer but are not actually used yet. This is valid for IP address and MAC address etc. These can not normally be used immediately because otherwise your present connection would break down
[remember Windows before XP! After a network change you had to reboot! Even with XP it takes some time since the process is not that simple]. Therefore modifying the IP only prepares it to be saved in FLASH. Saving it saves it to FLASH but still doesn't apply it. Network changes are quite critical and we are back in Windows 3.11 teritory. Make a reset and then it is easy...

3. After the reset, the new settings are finally used, but they have been flagged as temporary settings (the old ones are also still in FLASH as well and so can be returned by simply deleting the temporary set - which happens after 3 minutes with no contact).

If you do want to save them to FLASH and reboot with them already fully operational (old ones have been overwritten!) then simply save them using
fnSaveNewPars(SAVE_NEW_PARAMETERS); rather than
fnSaveNewPars(SAVE_NEW_PARAMETERS_VALIDATE);

It may take a little study to grasp the complete concept but you should realise then why your project is responding as it is and then you can modify things as you wish them to be. (there are also some details in http://www.utasker.com/docs/uTasker/uTaskerFileSystem.PDF from 9/14)

Last point.

In fact it is no problem to change IP on the fly if you really want to. Here's an example of how it can be done.

Code: [Select]
                unsigned char newIPAddress[] = {192, 168, 1, 75};
                temp_pars->temp_network.ucOurIP[0] = newIPAddress[0];
                temp_pars->temp_network.ucOurIP[1] = newIPAddress[1];
                temp_pars->temp_network.ucOurIP[2] = newIPAddress[2];
                temp_pars->temp_network.ucOurIP[3] = newIPAddress[3];
                fnSaveNewPars(SAVE_NEW_PARAMETERS);
                uMemcpy(&network, &temp_pars->temp_network, sizeof(NETWORK_PARAMETERS));
                fnDeleteArp();

This sets the new IP to the temporary structure.
It then saves the temporary structure to FLASH (this is valid also after next reset).
Then it copies from the temporary structure to the working structure (from this point IP, TCP etc. use it!!)
It is resommended to delete the ARP table since it will otherwise have entries which are possibly invalid for a new subnet.

The only thing which will cause troubles here is if it is change in an active connection (like via HTTP) since the connection will subsequently fail (the web server will probably show a blank page after a short time since it will time out).
This can also simply be avoided by not making the copy from temp_network to network immediately but rather starting a timer (say 2s). After the timer fires (the web page will have been served with the new details in the meantime) the copy can be effected. The browser has already closed the TCP connection in the meantime so no more error messages. But it will be necessary to connect the next time using the new address since the old one is no longer valid.

As you see, there should be no restrictions. However I still stick to the method with validation and timeouts since it ensures that no device is left stranded with invalid or unknown settings. Normally IP setup is not used a lot and so I prefer to play safe. Don't forget that you can use DHCP and there are various other network tricks allowing IP to be set
using ARP sequences and.... but that is another story!!

Cheers

Mark
« Last Edit: November 15, 2007, 08:25:17 PM by mark »

Offline twoerner

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: updating parameters via the HTTP
« Reply #4 on: July 19, 2007, 02:37:36 PM »
Our codes are in fact equivalent.

Well unless there's some side non-expected consequence of uStrcpy() then
Code: [Select]
uStrcpy(&cValue[(sizeof(cValidate) - 1)], cValidate); is not equivalent to
Code: [Select]
uStrcpy (cValue, "Validate");since the first example copies the string not at location zero but at a location the size of the string into the array.

Also for some reason you calculate the size as double the actual.

As you see, there should be no restrictions. However I still stick to the method with validation and timeouts since it ensures that no device is left stranded with invalid or unknown settings.

I think your idea of having a verify step is awesome, that's definitely one to put in the ol' toolbox of tips and tricks. I just did not think that the process required a 3-step procedure for the user, I believe the same results can be achieved using a 2-step procedure and was wondering if I had misunderstood your intentions.

Don't forget that you can use DHCP and there are various other network tricks allowing IP to be set
using ARP sequences and.... but that is another story!!

DHCP is a phase 2 item for my project :-)
I assume you're talking about gratuitous ARPs? Yes, very clever.

Thanks again!

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: updating parameters via the HTTP
« Reply #5 on: July 19, 2007, 04:32:14 PM »
Ooops

My original example was wrong. I didn't realise that I had added an offset to the string buffer. This was a cut and paste error and when I did the comparison I didn't compare with the incorrect case, but rather with the one I thought I had written.

Therefore my first example was reall over-complicated and indeed incorrect...

Regards

Mark