Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 11:19 07 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Pi-cromite: Next steps

     Page 2 of 2    
Author Message
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3019
Posted: 03:58am 12 May 2017
Copy link to clipboard 
Print this post

  MicroBlocks said  Also adding a line will not disturb the order.

There is no order implied in the ~nn tags, and none, I think, in Jim's. "~23" can be followed by"~14".

The values I replace the tags with are stored in a string array, indexed by the number following "~". The program provides a new value for the string array element when a sensor value changes. In the next html update, the new value is plugged in.

PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 05:02am 12 May 2017
Copy link to clipboard 
Print this post

I am used to update the page on the client side, and request only the changed data from the server. Javascript can be used for lots of nifty templates.
I find i have more control over the visual aspects by just building a HTML/CSS file that is static, and then use the server for data only.
That way i can easily build a page with tools that are made for it and i don't have to manage a lot of print# statements in basic.
Once pages show more then a few numbers and start to get some nice layout and visuals it starts to get very difficult and obscure when you not separate that part out of the basic program.
When building html nesting is often something that can go wrong easily. missing a closing tag can really screw up the layout.

Building a page with simple tools like for instance https://www.w3schools.com/html/tryit.asp?filename=tryhtml_intro makes it so much faster.

Microblocks. Build with logic.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8597
Posted: 06:26am 12 May 2017
Copy link to clipboard 
Print this post

Please find attached 5.3.a26

2017-05-12_195518_mmbasic.zip

NB file updated at 19:07 UTC to remove diagnostic print

Note "TRANSMIT HTTP 1.1" is changed to "TRANSMIT HTML"

This version implements a complete set of routines for handling long strings. Particularly useful for parsing out HTTP requests

These are taken from Geoff's long string CFunctions, but because CFunctions are impossible in the Pi-cromite they are included in the firmware.

The syntax is pretty much the same as the CFunctions although the way they are called is somewhat different.

Geoff's document is attached:

2017-05-12_162403_Long_Strings.pdf

and the changes are best understood by my test program. There is one additional routine which allows you to substitute characters into an existing string

LONGSTRING REPLACE array%() , newstring$, start-position



Note that unlike the CFunctions these calls all use integer arrays to hold the long strings. The calls all check for the arrays being big enough and give an error if any call would exceed the array limits.


Dim a%(100) 'enough for 800 character string
Dim b%(10)
LongString load a%(),16,"1234567890abcdef"
Print "chars 4-9 are: ", LGetStr$(a%(),4,6)
s$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
LongString append a%(),s$
Print "stringlength now :", LLen(a%())
If LInStr(a%(),"ghij") Then
Print "ghij found"
Else
Print "ghij not found"
EndIf
Print "convert string to lower case"
LongString lcase a%()
If LInStr(a%(),"ghij") Then
Print "ghij now found"
Else
Print "ghij now not found"
EndIf
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
LongString append a%(),s$
Print "stringlength now :", LLen(a%())
start=1
Do
p=LInStr(a%(),"ABC",start)
If p Then Print "ABC found at position ",p
start=p+1
Loop While p>0
Print "Convert to upper case"
LongString ucase a%()
p=LInStr(a%(),"ABC",start)
If p Then Print "ABC now found at position ",p
LongString left b%(),a%(),20
Print "left-most 20 characters of a% are ",LGetStr$(b%(),1,20)
LongString right b%(),a%(),20
Print "right-most 20 characters of a% are ",LGetStr$(b%(),1,20)
LongString mid b%(),a%(),20,20
Print "chars 20-39 characters of a% are ",LGetStr$(b%(),1,20)
Print "Now clear a%"
LongString clear a%()
Print "a% is now ",LLen(a%()), " characters long"
Print "copy b% to a%"
LongString copy a%(),b%()
If LCompare(a%(),b%())=0 Then Print "Compare :the strings are the same"
Print "a% is now ",LLen(a%()), " characters long"
LongString concat a%(),b%()
Print "a% is now ",LLen(a%()), " characters long"
If LCompare(a%(),b%())=1 Then Print "a% now bigger than b%"
If LCompare(b%(),a%())=-1 Then Print "b% now smaller than a%"
Print "b% is currently ",LGetStr$(b%(),1,30)
LongString replace b%(),"hello",5
Print "b% is now ",LGetStr$(b%(),1,30)

Edited by matherp 2017-05-13
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5915
Posted: 08:11pm 12 May 2017
Copy link to clipboard 
Print this post

I have noticed a few strange events with the random number generator.
> list
For n = 1 To 20
Print Rnd()*100
Next n

> run
1.630068
24.2887
13.7231
80.4176
15.6679
40.0944
12.979
10.8809
99.8924
21.8257
51.2932
83.9111
61.2639
29.6031
75525711
52.4287
49.3582
97.2774
29.2516
77.1357
>

>
> run
97.94334
74.381
90.3365
98.3595
66.688
49.7258
16.3968
83.0011
88.8948
7.69946
64.9706
24.8044
947.8909
22.9137
70.0619
31.6867
32.8777
23.1428
7.41609
63.3072
>
>


The first issue is the way that the first printout in the list 'usually' omits the leading space. Not always and once the second line did it as well.

The big problem is the occasional number that is way out of range.
This happens about every 15-20 time I run the program.

I also noticed a repeated sequence but I think it only happens with a mmbasic restart.

Edited by TassyJim 2017-05-14
VK7JH
MMedit   MMBasic Help
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8597
Posted: 11:58pm 12 May 2017
Copy link to clipboard 
Print this post

Please find attached 5.3.a27

2017-05-13_104231_mmbasic.zip

This uses the time to initialise the random number generator and it also includes three new options on the TRANSMIT command

The first is used to tell the browser that it is asking for something we can't serve

Transmit NULL


This sends the string "HTTP/1.0 404\r\n\r\n"

This can be used for responding to an invalid page or a FAVICON request if you don't have an icon

The second allows us to send a style sheet

Transmit CSS "cssfilename"


This sends the css file "cssfilename" if it exists or a NULL response if it doesn't.

The third is used for responding to a favicon request

Transmit FAVICON


This send the icon file favicon.ico if it exists or a NULL response if it doesn't

Use of these is demonstrated in the attached demo program. Note the use of the long string handling to simplify the parsing.

Dim a%(100)
Dim crlf$=Chr$(13)+Chr$(10)
Dim q$=Chr$(34)
Open "socket,myint,100" As #2
Do
Loop
Sub myint
'load the request
Do While Not Eof(2)
LongString append a%(), Input$(10,2)
Loop
p%=LInStr(a%(),"GET",1)
t%=LInStr(a%(),"HTTP",1)
s$=LGetStr$(a%(),p%,t%-p%)
Print s$
LongString clear a%()
'
If Instr(s$,"favicon") Then
Transmit FAVICON
Else If Instr(s$,"styles") Then
Transmit CSS "styles.css"
Else
Print #2,"<html><head><title>My test</title>";
Print #2,"<link href="+q$+"styles.css"+q$;
Print #2," rel="+q$+"stylesheet"+q$+" type="+q$+"text/css"+q$+"></head>";
Print #2,"<body>The body</p>"+Time$+"</body></html>"+crlf$;
Transmit HTML
EndIf
End Sub


The simple style sheet I used was

body {
background-color: powderblue;
}


saved in the same directory as mmbasic as "styles.css"

The favicon I use is the raspberry pie one

2017-05-13_104113_favicon.zip

also saved in the same directory as mmbasic

Jim: I can't replicate your formatting issue on either a Pi 3 or Pi zero W. It may be some sort of local networking issue.

Next steps are to handle other image file types

Does anyone want to design a MMBasic favicon? We really ought to have one

Edited by matherp 2017-05-14
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3668
Posted: 12:56am 13 May 2017
Copy link to clipboard 
Print this post

You may need to read the RFCs for HTTP, MIME, etc

I dimly recall Content- headers (Content-coding, Content-type, etc) and related headers (Accept- etc).

There's no doubt example code on the net :)

JohnEdited by JohnS 2017-05-14
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 01:12am 13 May 2017
Copy link to clipboard 
Print this post

@Matherp, nice progress.

It might be better to use
[code]
TRANSMIT 404
[/code]
Instead of using NULL.
There are a lot of codes that are very useful.
My suggestion would be that when a number follows the TRANSMIT command it will be a HTTP status code.
Otherwise it will be a content-type followed by a optional filename.
You would then also be able to send a static html file with
[code]
TRANSMIT HTML "index.htm"
[/code]
Same as you do now with a CSS file.
Another great option would be to use a variable to contain the filename.
Being able to use a filename variable would allow the programmer to extract the filename out of the URL
You can then add all other things in a similar way.
[code]
TRANSMIT JAVASCRIPT "myscripts.js"
TRANSMIT JAVASCRIPT jsFilename$ 'filename in a variable.

TRANSMIT PNG "tiger.png"
TRANSMIT JPG "tiger.jpg"
[/code]

HTML,JAVASCRIPT,PNG,CSS etc could then be defined constants that stand for a full content-type.
If you want to use a specific content-type then it would be nice to use the following
[code]
TRANSMIT "application/vnd.ms-excel" "mysheet.xls"
[/code]
It would be impossible to have a keyword for every used content-type (see http://www.iana.org/assignments/media-types/media-types.xhtml for a list) so having the possibility to use a string would allow any content to be send.

If sending a css file and favicon works then you already have everything in place to send other content types.

Microblocks. Build with logic.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8597
Posted: 04:26am 13 May 2017
Copy link to clipboard 
Print this post

Attached 5.3.a28

2017-05-13_140515_mmbasic.zip

Thanks to MicroBlock for the ideas I think I've got something interesting working

I've simplified things as follows:

Transmit now has just three options

TRANSMIT CODE NNN


This sends a simple response: "HTTP/1.0 NNN\r\n\r\n"

Note the code is always three digits

TRANSMIT HTML


This constructs a header for an HTML page and sends any data that has been buffered using "PRINT #" to an opened socket.

TRANSMIT FILE "filename", "content-type"

This constructs a header with the content type specified and the length of the file, sends it and then sends the contents of the file

This should now cater for pretty much anything.

The example program serves a simple html page with a css sheet, a favicon, and an embedded jpeg image. The full list of content types are detailed in the link in the post from MicroBlocks above.

Dim a%(100)
Dim crlf$=Chr$(13)+Chr$(10)
Dim q$=Chr$(34)
Open "socket,myint,100" As #2
Do
Loop
Sub myint
'get the request
Do While Not Eof(2)
LongString append a%(), Input$(10,2)
Loop
p%=LInStr(a%(),"GET",1)
t%=LInStr(a%(),"HTTP",1)
s$=LGetStr$(a%(),p%,t%-p%)
Print s$
LongString clear a%()
'
If Instr(s$,"favicon") Then
Transmit FILE "favicon.ico","image/vnd.microsoft.icon"
Else If Instr(s$,"styles") Then
Transmit FILE "styles.css","text/css"
Else If Instr(s$,"tiger-3.jpg") Then
Transmit file "tiger-3.jpg","image/jpeg"
Else
Print #2,"<html><head><title>My test</title>";
Print #2,"<link href="+q$+"styles.css"+q$;
Print #2," rel="+q$+"stylesheet"+q$+" type="+q$+"text/css"+q$+"></head>";
Print #2,"<body>The body</p>";
Print #2,"<img src="+q$+"tiger-3.jpg"+q$+" alt="+q$+"mypic"+q$+"><p>";
Print #2,Time$+"</body></html>"+crlf$;
Transmit HTML
EndIf



There is one more (hard!) bit of the puzzle to do and this is to take a static HTML file and automatically embed in it variable data. There have been lots of great suggestions for this above. My instinct is to follow MicroBlocks and use {} around the variable name. My intention is only to support simple string variables so that it will be up to the MMBasic programmer to maintain these from the relevant numeric values using STR$

The TRANSMIT HTML command will be extended to support an optional filename and will automatically do the data merge as it sends the file

Thoughts?

Edited by matherp 2017-05-14
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 04:58am 13 May 2017
Copy link to clipboard 
Print this post

That will work!

An automatic replacement of values in {} by their variable content would be indeed the easiest way to manipulate a html.

What i often do is created html snippets on the server that the client can insert into the main html document.

Having the possibility to read a file (any file?), replace all {variable} instances with values and then send it would be super.

On a Windows Server t is easy to just read the whole file in memory and then do all the replaces. But for a smaller system it would be enough to just read it and process it line by line. CR+LF would then be the most obvious delimiter. In HTML CR and LF are skipped so defining a html file with reasonable length lines is very doable.

If you are up to it there are a few more things that can make live easier.

First: Allow extra headers to be send.
This will then give the option to allow cross domain scripting.
This header will allow all pages from all domains to request data:
[code]
Access-Control-Allow-Origin: *
[/code]
The * means any, you can also allow only certain domains.
This will give the possibility to integrate data gathered on the Pi-cromite to be display on any website.
Normally the browser will not allow to request data cross domain, this header is like a 'whitelist' of domains that are allowed to.

There are many other headers that can be very helpful. Like caching headers and to many to mention. Here is a list: https://msdn.microsoft.com/en-us/library/ms537417(v=vs.85).aspx

maybe it could be done by allowing an extra parameter to the TRANSMIT command.
[code]
Dim HeaderArray(2)
HeaderArray(0) = "Access-Control-Allow-Origin: *"
HeaderArray(1) = "Cache-Control: max-age=68000"
TRANSMIT "data.csv", "text/csv", HeaderArray
[/code]
Above example allows websites from any domain to request the data. And the data is suggested (by the server) to be cached (on the client) for 68000 seconds.

Second.
To make parsing easier you could parse the request in the firmware and expose a headers array. This will allow the programmer to quickly iterate through them.

The first is important if the data has to be shown or shared with other websites and have more control about what is being sent.

The second is a nice to have as it makes parsing simpler.

Edited by MicroBlocks 2017-05-14
Microblocks. Build with logic.
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 1986
Posted: 07:31am 13 May 2017
Copy link to clipboard 
Print this post

the idea of {} is useful as a general feature in string manipulation - reminds me of mailmerge templates...Edited by CaptainBoing 2017-05-14
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3019
Posted: 11:37am 13 May 2017
Copy link to clipboard 
Print this post

Perhaps as an option, if {} encloses a number, that would be an index into a text array containing the value to be inserted.


PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
     Page 2 of 2    
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024