Monday, 23 September 2019

Javascript

JavaScript is a high-level scripting language that has become one of the core components of the World Wide Web.
Originally used client side in a user’s browser, it has migrated back to the server and is also used for general scripting purposes.

Windows

JavaScript is one of many languages supported by the Windows Scripting Host (WSH).

Hello World

The following is a JavaScript program using the Windows Scripting Host.
The file is called helloworld.js.

WSH.Echo("Hello world");
WSH.Quit();

Create the file with your favourite plain text editor (Notepad or better, but not a word processor, they tend to add lots of tat).

Save the file.

Bring up the command line interface (search for cmd).

Use the change directory command to move to where you have saved the file (if you have spaces in the folder names, enclose the path in double quotes).

To execute the file type:
cscript helloworld.js
This is what you will get (Windows 10 machine - YMMV)

C:\some\folder\tree>cscript helloworld.js
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

Hello world

C:\some\folder\tree >
An alternative is to use a WSF file (.wsf). This requires the <job> or <package> tags around the script. Because WSF files could contain any supported language (or indeed multiple languages) you need to define the language within a script tag.
<job>
    <script language="JScript">
        WSH.Echo("Hello world");
        WSH.Quit();
    </script>
</job>

C:\some\folder\tree >cscript helloworld.wsf
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

Hello world

C:\some\folder\tree >

HTML

The following is extremely simple.
The script is executed when the page is loaded but before it is displayed. It is possible to execute the JavaScript after the page has loaded or in response to some event.
<!DOCTYPE html>
<html>
    <head>
        <title>Javascript in HTML</title>
    </head>
    <body>
        <p>Testing Javascript</p>
        <script language="JScript">
            alert("Hello world!");
        </script>
    </body>
</html>
Save the file as helloworld.html.
Because this is displayed in your browser, the display will vary.

Linux

Raspberry Pi

From Raspbian Stretch onwards, most standard installs of Raspbian come with node.js installed as standard.
You can check if it is installed by running:
node -v
On the command line. If it is installed, it will return the version number.
If your installation does not have node.js, install using:
sudo apt-get install node
sudo apt-get install npm
The program is just one line:
console.log("Hello world!");
Using terminal, change the directory to where you have saved the file, you can run it by typing:
node helloworld.js
The result will be similar to:
pi@raspberrypi:~/Documents/JavaScript $ node helloworld.js
Hello world!
pi@ raspberrypi:~/Documents/JavaScript $

Useful functions

Splitting Strings

The following is a Windows specific example.
WSH.Echo("Test code");

WSH.Echo(splitString("-2MKptcmt1Q,W3XlnfNPk6I,dRYRcM-HHvY"));

 function splitString(aString){
    WSH.Echo(aString);
    result = "";
    anArray=[];
    anArray = aString.split(",");
    for(ix = 0;ix<anArray.length;ix++){
        result = result +"*" +(anArray[ix])+"*";
    }
    return result;
}


References

https://en.wikipedia.org/wiki/JavaScript
https://en.wikipedia.org/wiki/ECMAScript
https://www.w3schools.com/js/default.asp
https://www.w3schools.com/jsref/default.asp

https://en.wikipedia.org/wiki/Windows_Script_Host
https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cscript
https://docs.microsoft.com/en-us/previous-versions//98591fh7(v=vs.85)

https://www.instructables.com/id/Javascripting-Your-RaspberryPi/


Sunday, 15 September 2019

Traverse a website with Python

One thing that is important when building a website is that the links on the site connect up.

One way of doing that is to find all the links and then use them.

The following code will find all the links on the first page, and then will visit all the links that point to the same site.

Do not point this at Wikipedia!
# Functions to traverse a website
from lxml import html
import requests
def web_traverse(aURL):
    siteURLs=[]
    
# Get the page from the URL
    page = requests.get(aURL)
# Make an HTML tree from the text
    tree = html.fromstring(page.content)
    tree.make_links_absolute(aURL, resolve_base_href=True)
# Extract urls from the HTML tree
    for  alink in tree.xpath("//a"):
        siteURLs.append(alink.get("href"))
    return siteURLs

def recursive_traverse(aBaseURL,aURL,aLinks):
    print("Traversing " +aURL)
    siteURLs=web_traverse(aURL)
    if siteURLs is not None:
        #print(siteURLs)
        for aLink in siteURLs:
            if aLink is not None:
                if aBaseURL in aLink :
                    if aLink not in aLinks:
                        print("found link:"+aLink)
                        aLinks.append(aLink)
                        aLinks=recursive_traverse(aBaseURL,aLink,aLinks)
    return aLinks
    

    
if __name__ == "__main__":
    # execute only if run as a script
    baseURL="https://technologyisnotdull.blogspot.com"
    #c=web_traverse(baseURL)
    c=recursive_traverse(baseURL,baseURL,[])
    if True:
        print("Links found:")
        for thing in c:
            print (thing )
            #print ((len(thing)))

Monday, 12 August 2019

Fortran on the Raspberry Pi

Introduction

My first programming job was in Fortran (Fortran 77 on an HP-150 with an HPIB connection to an I/O board). I have not used Fortran for probably thirty years but thought I should have a look at trying it on the Raspberry Pi.
Fortran is not just a very long lived language, unlike COBOL which has survived because core parts of the financial sector have stable working elements that they do not want disturbed, Fortran is still a developing system - its continued use in high powered mathematical processing celebrates the origin of its name "Formula translation".

Installation

Make sure that the operating system is up to date:
sudo apt-get update
sudo apt-get upgrade
Then install GFortran:
sudo apt-get install gfortran

First program

I added a Fortran directory to my Documents directory for source code.
Here is a simple "Hello World" program:

program helloworld
print *,"Hello World"
end program helloworld

Create the file in your favourite editor and save it into the directory.
In the terminal window, change the current directory to the saved location.
Compile using:
gfortran -o helloworld ./helloworld.f90
In the terminal enter the following:
./helloworld
The program will then print Hello World.

Using the Geany IDE

Geany is a default install on Raspbian, and makes it a lot easier to write programs than a simple text editor.
The application can be found by clicking on the Applications Menu/Programming/Geany Programming Editor.

Enter the program code (there is syntax highlighting once you have named the file with a suitable suffix, in this case: .f90 for Fortran 90).
To build and execute the program, click on Build/Execute. Geany will build then execute the code in a shell.



References
https://en.wikipedia.org/wiki/Fortran
https://gcc.gnu.org/fortran/
https://gcc.gnu.org/wiki/GFortran
https://en.wikipedia.org/wiki/IEEE-488
https://en.wikipedia.org/wiki/HP-150
https://en.wikipedia.org/wiki/Geany
https://geany.org/


Friday, 9 August 2019

Analysing file content - a simple Python program

I needed to describe the structure of a simple PDF file as part of a presentation, so I thought it would be an interesting to see how an actual (working) example was laid out.

The file contents were created by copying the text from the example in appendix H3 in the ISO 32000 reference document (available from the Adobe site) and pasting them into an empty file. Some tidying up took place as the copy included some extraneous characters.

This is how the file displayed.

This is the Python program used to read and display the file contents and offsets.

# Open and read the contents of a newline delimited file and display
filename="/home/pi/Documents/simplepdf.pdf"
# Open file for read as bytes
with open(filename, "rb") as f:
    # Initialise variables
    addr=0                  # Current byte count
    line_number = 0         # Line number displayed
    lineoftext = ""         # Accumulated text for a line
    startlineaddr = 0       # Off set for start of accumulated text
    
    byte = f.read(1)        # Read a byte from the file
    while byte != b"":      # While something has been read
        addr+=1                # Increment byte count
        if byte==b"\n":        # If byte is newline character
            line_number += 1        # Increment line number
                                    # Print line number, offset and line of text
            print("{:03d}".format(line_number)+"-"+"{:05d}".format(startlineaddr)+":"+lineoftext)
            lineoftext=""           # Clear line of text
            startlineaddr=addr      # set offset of new line of text
        else:
            try:                # Decode byte as a utf-8 character,
                                # if it fails use default string conversion 
                lineoftext = lineoftext + (byte.decode("utf-8"))
            except UnicodeDecodeError:   
                lineoftext = lineoftext + str(byte)
        byte = f.read(1)
    # If there is any undisplayed text left, display it
    if lineoftext !="":
        line_number += 1
        print("{:03d}".format(line_number)+"-"+"{:05d}".format(startlineaddr)+":"+lineoftext)
    # Display file length
    print(str(addr) + " Bytes")

This is the output.

001-00000:%PDF-1.4 
002-00010:1 0 obj
003-00018: << /Type /Catalog 
004-00038: /Outlines 2 0 R
005-00055: /Pages 3 0 R 
006-00070: >>
007-00074:endobj
008-00081:
009-00082:2 0 obj
010-00090: << /Type /Outlines
011-00110: /Count 0 
012-00121: >>
013-00125:endobj
014-00132:
015-00133:3 0 obj
016-00141: << /Type /Pages
017-00158: /Kids [4 0 R]
018-00173: /Count 1 
019-00184: >>
020-00188:endobj
021-00195:
022-00196:4 0 obj
023-00204: << /Type /Page
024-00220: /Parent 3 0 R
025-00235: /MediaBox [0 0 612 792] 
026-00261: /Contents 5 0 R 
027-00279: /Resources << /ProcSet 6 0 R
028-00309:   /Font << /F1 7 0 R 
029-00332:   >> 
030-00339: >>
031-00343:>> endobj
032-00353:5 0 obj
033-00361:<< /Length 73 >>
034-00378:stream 
035-00386: BT
036-00390: /F1 24 Tf
037-00401: 100 100 Td
038-00413: (Hello World) Tj
039-00431: ET 
040-00436:endstream
041-00446:endobj
042-00453:
043-00454:6 0 obj
044-00462: [/PDF /Text]
045-00476:endobj
046-00483:
047-00484:7 0 obj
048-00492: << /Type /Font
049-00508: /Subtype /Type1
050-00525: /Name /F1
051-00536: /BaseFont /Helvetica
052-00558: /Encoding /MacRomanEncoding
053-00587: >> 
054-00592:endobj
055-00599:
056-00600:xref
057-00605:0 8
058-00609:0000000000 65535 f 
059-00629:0000000009 00000 n 
060-00649:0000000074 00000 n 
061-00669:0000000120 00000 n 
062-00689:0000000179 00000 n 
063-00709:0000000364 00000 n 
064-00729:0000000466 00000 n 
065-00749:0000000496 00000 n
066-00768:
067-00769:trailer
068-00777:<< /Size 8
069-00788: /Root 1 0 R 
070-00802: >>
071-00806:startxref 
072-00817:625 
073-00822:%%EOF
827 Bytes
>>> 

Interestingly XPDF, Chrome and Apple Preview happily display the source file, even though the xref table (line 58 onwards) does not line up with the objects in the file.

More on that later.

References:

Thursday, 1 August 2019

Tuesday, 30 July 2019

Installing MySQL on the Raspberry Pi - part 3: Connecting from .Net

Installing the Connector

Visual Studio is not supplied with a default MySQL/MariaDB connector.
Use the MySQL connector.
https://dev.mysql.com/doc/connector-net/en/connector-net-installation.html
Run the installer.
 image
Select Typical installation
 image
In Visual Studio, to add the connector go to the Project/Add Reference. Select Assemblies and search for MySQL. Remember you will need to do this for each project (even within a solution).
 image
Tick MySQL.Data and click on OK.

Example program in VB.Net

The program uses a simple form.
One vertical Split Container, with one button in one panel, and a multi-line, docked text box with vertical scroll bar in the other panel.

Code

Public Class Form1
    ' *** Test application - 
    ' *** to a remote MariDB database, insert a row and then display all rows
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim myDB As New MySql.Data.MySqlClient.MySqlConnection("Server=192.168.1.191;Database=datastorage;Uid=datawriter;Pwd=*******;")
        Dim myCommand As New MySql.Data.MySqlClient.MySqlCommand()
        Dim myReader As MySql.Data.MySqlClient.MySqlDataReader
        Dim sSQL As String
        addtext("Connecting")
        myDB.Open()
        addtext("Connected")

        addtext("Inserting")

        sSQL = "insert into datavalues(user,title,value) values(CURRENT_USER(),'VBtest',23);"

        With myCommand
            .Connection = myDB
            .CommandText = sSQL
            .ExecuteNonQuery()
        End With
        addtext("Inserted")


        sSQL = "SELECT * FROM datavalues"
        addtext("Selecting")

        With myCommand
            .CommandText = sSQL
            myReader = .ExecuteReader()
        End With
        addtext("Selected")

        addtext("Reading")

        While myReader.Read()
            Dim sLine As String = ""
            For ix As Integer = 0 To myReader.FieldCount - 1
                If sLine <> "" Then
                    sLine = sLine & ", " & myReader.GetString(ix)
                Else
                    sLine = myReader.GetString(ix)
                End If
            Next
            addtext(sLine)
        End While
        addtext("Reading")
        addtext("Closing")
        myReader.Close()
        myDB.Close()
        addtext("Closed")
    End Sub
    ''' <summary>
    ''' Add string parameter to current content of text box
    ''' </summary>
    ''' <param name="aString">Text to be added to text box </param>
    Private Sub addtext(aString As String)
        TextBox1.Text = TextBox1.Text & aString & vbCrLf
    End Sub
End Class

Output

Connecting
Connected
Inserting
Inserted
Selecting
Selected
Reading
1, root@localhost, test, 1, 27/02/2019 11:06:09
2, root@localhost, test, 2, 27/02/2019 11:06:16
3, root@localhost, test, 3, 27/02/2019 11:06:23
5, datawriter@192.168.1.%, test, 30, 28/02/2019 13:13:07
6, datawriter@192.168.1.%, test, 30, 28/02/2019 13:13:23
7, datawriter@192.168.1.%, test, 30, 30/07/2019 08:06:21
8, datawriter@192.168.1.%, VBtest, 23, 30/07/2019 10:49:39
9, datawriter@192.168.1.%, VBtest, 23, 30/07/2019 10:58:02
Reading
Closing
Closed

Example Code in C#

This is a console application.

Code

using System;

using MySql.Data.MySqlClient;

public class MySQLTest
{
    public static void Main()
    {
        string connStr = "Server=192.168.1.191;Database=datastorage;Uid=datawriter;Pwd=********;";
        MySqlConnection myDB = new MySqlConnection(connStr);
        try
        {
            Console.WriteLine("Connecting");
            myDB.Open();
            Console.WriteLine("Connected");
            Console.WriteLine("Inserting");

            string sql = "insert into datavalues(user,title,value) values(CURRENT_USER(),'C#test',54);";
            MySqlCommand myCommand = new MySqlCommand(sql, myDB);

            myCommand.ExecuteNonQuery();
            Console.WriteLine("Inserted");

            Console.WriteLine("Selecting");
            sql = "SELECT * FROM datavalues";
            myCommand.CommandText = sql;

            MySqlDataReader myReader = myCommand.ExecuteReader();
            Console.WriteLine("Selected");

            Console.WriteLine("Reading");

            while (myReader.Read())
            {
                string rowtext = "";
                for (int ix = 0; ix < myReader.FieldCount; ix += 1)
                {
                    if (rowtext == "")
                    {
                        rowtext = string.Concat("", myReader[ix]);
                    }
                    else
                    {
                        rowtext = string.Concat(rowtext,", ", myReader[ix]);
                    }
                }
                    Console.WriteLine(rowtext);              
            }
            myReader.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        myDB.Close();
        Console.WriteLine("Done.");
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

Output

Connecting
Connected
Inserting
Inserted
Selecting
Selected
Reading
1, root@localhost, test, 1, 27/02/2019 11:06:09
2, root@localhost, test, 2, 27/02/2019 11:06:16
3, root@localhost, test, 3, 27/02/2019 11:06:23
5, datawriter@192.168.1.%, test, 30, 28/02/2019 13:13:07
6, datawriter@192.168.1.%, test, 30, 28/02/2019 13:13:23
7, datawriter@192.168.1.%, test, 30, 30/07/2019 08:06:21
8, datawriter@192.168.1.%, VBtest, 23, 30/07/2019 10:49:39
9, datawriter@192.168.1.%, VBtest, 23, 30/07/2019 10:58:02
10, datawriter@192.168.1.%, test, 30, 30/07/2019 13:28:56
11, datawriter@192.168.1.%, C#test, 54, 30/07/2019 13:42:00
12, datawriter@192.168.1.%, test, 30, 30/07/2019 13:43:13
13, datawriter@192.168.1.%, C#test, 54, 30/07/2019 13:45:37
14, datawriter@192.168.1.%, C#test, 54, 30/07/2019 13:47:51
15, datawriter@192.168.1.%, C#test, 54, 30/07/2019 13:48:04
16, datawriter@192.168.1.%, C#test, 54, 30/07/2019 13:52:03
17, datawriter@192.168.1.%, C#test, 54, 30/07/2019 13:56:07
Done.
Press any key to exit.

Wednesday, 24 July 2019

GoPro Wifi connection - part one

Background

The GoPro series of cameras have become synonymous with action cameras in general. Earlier versions have had a WiFi backpack, later versions have the WiFi option built in.

I have an elderly GoPro Hero2, that has survived three leaks - thankfully all in fresh water.


They are rust marks on the shutter button and surroundings.


Unfortunately, the only official way of connecting to a GoPro is either via their Android application, or via their PC or Mac applications. If you are using older hardware, or Linux based operating systems, there appears to be no official connection.
However, a search of the internet found the first referenced article. Once the IP address was discovered, it was a lot easier to find the other references, and more importantly the GoProWifiHack on GitHub.

Connecting to the GoPro webserver

If the GoPro has an external WiFi backpack, connect it to the back of the GoPro.

It is worth plugging in the power to the backpack, as you might spend more time on it than you expect.

Switch on the WiFi. The Wifi device name should appear on the list of available networks on your computer.

Now my GoPro Hero 2 had been set up previously, so I was able to select the connection, enter the password and connect to the device.

Now the key piece of information is the availability of a web interface.

This is located at 10.5.5.9:8080. From there you can access the videos and stills on the device.


Next - sending commands.

References

http://aikiwolfie.blogspot.com/2014/12/ubuntu-tip-connecting-to-gopro-hero4.html
https://github.com/KonradIT/goprowifihack
https://github.com/KonradIT/goprowifihack/blob/master/HERO2/README.md
https://github.com/KonradIT/goprowifihack/blob/master/HERO2/WifiCommands.md
https://github.com/KonradIT/goprowifihack/blob/master/HERO2/Mediabrowsing.md