Datacontext voor directories voorbeeld

Datacontext voor directories: een voorbeeld (met in groen hoe het er uit ziet in het configuratie/settings bestand)

De code

dim bOk as boolean

We leggen bv eerst vast hoe onze dirset gaat heten*:

bOk = newDirSet("Export")

[DirSet]
Export = ""

Best een beschrijving geven om uit te leggen wat hiermee moet gebeuren:

updDirSet(“Export”, “Dir for data export from this application”)

[DirSet]
Export = "Dir for data export from this application"

Kan ook in één keer:

bOk = newDirSet("Export", "Dir for data export from this application")

.. met hetzelfde resultaat als boven in het settings bestand; toon beschrijving van..

print getDirSetDescription("Export")

Dir for data export from this application

We kunnen alle (in configuratiebestand) bestaande dirsets opvragen:

arrString[] = getAllDirSetNames()

Directory path opslaan

En nu het belangrijkste: een directorypath bewaren voor een bepaalde dirset; hier context 0 **:

setDirValue(0, "Export", "path", "/home/copyleft/Data/Export")

[Datacontext0-Export]
path = "/home/copyleft/Data/Export"

(**) Als een datacontext in gebruik is kan je de huidige id opvragen:

print hDataContext.getCurrentContextId()

En dan écht het belangrijkste: getDirValue opvragen; hier tonen we hem enkel:

print "We export to: " & getDirValue(hDataContext.getCurrentContextId(), "Export", "path")

We export to: /home/copyleft/Data/Export

De directory opvragen gebeurt in je applicatie op het moment dat je daar iets mee wil doen; bv een tekst bewaren in een bestand:

File.Save(getDirValue(0, "Export", "path") &/ "ExportOfTheDay.txt", sText);

Intern gebruikt DataContext deze methode om de Settings te maken:

print getContextDirSet(0, "Export")

Datacontext0-Export

Wat er in het bestand zo uitziet (zie ook hierboven):
[Datacontext0-Export]
...

(*) De naam “Export” zal misschien vastliggen in je applicatie, of laat je daar kiezen.

Ook de sleutel “path” kan je in principe kiezen. De Datacontext bewaart er verder nog de datum van aanmaak en laatste wijziging bij, die kan je nazien in het configuratiebestand (momenteel nog niet vanuit een methode in de library, tenzij je in getDirValue de juiste sleutel meegeeft, zoals csKEYMODIFIED, zie definities in DataContext class).

Andere voorbeelden

  • Import : bv om txt bestanden in te lezen
  • Pictures: bv iconen of beeldmateriaal waarnaar gelinkt wordt / om ze te laden in de applicatie
  • Export : zoals hierboven, bv om vanuit een applicatie een CSV export bestand te maken en dat op een vaste plaats voor de gebruiker te bewaren.
  • Cam: opgenomen beeld met webcam

DataContext: het unieke van het gebruik met het datacontext concept is dat je voor iedere “DataContext” aangepaste directory locaties kan opslaan. Door de datacontext om te schakelen gebruik je andere databases en andere directories, bv:

  • Datacontext0 = “Dev”, locale map op mijn laptop waarop ik programmeer; en de databaseverbindingen gaan naar mijn “localhost” database met testgegevens.
  • Datacontext1 = “live”, een map op een server of nextcloud die gedeeld wordt met andere gebruikers, en de database instellingen spreken de echte servers met live aan.

Toegepast op ons voorbeeld zou ons instellingenbestand zoiets bevatten (de database gegevens even weggelaten):

[DataContext0]
Name = "Live"
Description = "Echte gegevens, in gebruik

[DataContext1]
Name = "Dev"
Description = "Ontwikkelomgeving local(host)"

[DirSet]
Name = "Export"
Description = "Export csv files here"

[DataContext0-Export]
path = "/nextcloud/shared/myappdata/out"
created = "01/01/2024"

[DataContext1-Export]
path = "/nextcloud/shared/myappdata/out"
created = "03/01/2024"

...


Compileren met debug info

Soms kan het nuttig zijn om je programma te compileren mét de debug informatie aan, het is een parameter die je kan instellen in de IDE.

In een script: parameter -g bij de opdracht gbc:

gbc3 -g -a 2> log.txt

gevolgd door

gba3 -o $targetdir/gb3run/$targetbase.gambas

Gambas is back! Gambas3 is terug in openSUSE!

Na een onderbreking van een paar maanden ben ik verheugd Gambas terug gemakkelijk te kunnen installeren in OpenSUSE, namelijk in versie 15.6. (geïnstalleerd, upd: ook gebruikt).

Stappen:
verse 15.6
Na een update van opensuse 15.5 naar 15.6 ging ik op zoek naar de vroegere bron van Gambas(3) in openSUSE: Munix.

Munix repo
Repository toegevoegd via YAST:
https://download.opensuse.org/repositories/home:/munix9/ (URL link)
En met 15.6 hebben we geluk: gambas3 is weer voorzien:
bv gambas3-runtime-3.19.5-lp156.2.1.x86_64.rpm
ps: En (voorlopig nog) niet in 16.0.

Software Installeren: gambas3
Selecteren:
gambas3 – Complete visual development environment for Gambas
Version: 3.19.5

Installation Successfully Finished
Packages
Installed Packages: 139
autoconf, automake, bison, bison-lang, dwz, gambas3, gambas3-dev-tools, gambas3-gb-args… (more)

Continue reading

Een half als string is dubbel zo lang (“½”)

Kan het symbool “½” gebruikt worden in code, en in de database?

– in code: ja, maar
– database: te checken (op mijn mysql/mariadb: ja)

Lengte van een half
Maak een string met het half symbool er in, bv sExample = “½ eenheid”.
Doe string bewerkingen op die string, zoals de eerste letter van..

Print Left(sExample, 1)

Geeft niet het gewenste “½”

Print Left(sExample, 2)

Geeft wel het gewenste “½”

Datums, databanken en Gambas

Ik heb een paar keer problemen gehad met datum/tijd in Gambas, meestal gecombineerd met het opslaan in een databank, of er terug uit ophalen (*).

Bug
Op een bepaald moment werd er een bug gemeld op de mailinglist:

[Gambas Bug Tracker] Bug #1321: Converting date to string behavior change between 3.10 and 3.11

Gebruikers hadden ontdekt dat bepaalde programma’s, bepaalde broncode, niet meer werkte na een update van Gambas3 (overgang 3.10 naar 3.11 of hoger).

De bug-melding werd verworpen.

Correctie
Maar die verandering werd bevestigd; het was echter geen bug; ze was het gevolg van het verbeteren van een bug; er zat een fout in vroeger Gambas-code, en die was met deze versie-wissel gecorrigeerd, waardoor Gambas inderdaad anders reageert in sommige situaties.

Str() Val() Format() en Date() maken gebruik van de “locale”, de instellingen van de “desktop” (taal/land/tijd/etc).

CStr() gebruikt de UTC tijd.

Dus je moet kijken naar de instelling van de database en die van je desktop, bv GMT+0200.

In één programma CDate() en Date() mengen zal waarschijnlijk problemen geven.

De interne manier om een datum of tijd bij te houden is een getal, relatief tov een denkbeeldig nulpunt.

Met Format(), Date() maak je een interpretatie waarin je tijdzone meegenomen wordt om het voor jou “aanschouwelijk juist” te maken.

Bv in Groot-Brittanië is een datum/tijd opgeslagen in een record.
Als jij die opvraagt en toont met Format() dan krijg je de tijd die het in jouw tijdszone was, niet wat letterlijk opgeslagen is in de database.

Je moet dus ook opletten (voor het verschil)
– of je de database een datum laat opslaan, bv automatisch (instelling db server) met de instelling timestamp.
– of je zelf een datum naar de database stuurt als tekst: .. values('2024-01-01 01:14:18')
– of je kan in je SQL statement de opdracht voor een datum geven

Database
De database (mysql/mariadb) heeft 5 tijdsgebonden opslagvormen (kolom):

  • DATE = aleen de datum (1000-01-01-9999-12-31)
  • DATETIME = datum + tijd (1000..:..- 9999...:..)
  • TIMESTAMP datum + tijd (1970-20238!!!!)
  • YEAR : alleen een jaartal (1901-2155)
  • TIME : alleen een tijd (getal -838.. tot + 838.. ong 35 dagen)

Het 2038 probleem

Het hangt er natuurlijk een beetje vanaf wat je met die datums wil doen, en daarom moet je rekening houden met hun bereik, meestal vooral met hun hoogst mogelijke waarde, die voor sommige formaten gevaarlijk dichtbij komt.

Als je de datum enkel opslaat als leesbare informatie voor de programmeur, is 2038 van timestamp geen probleem, maar als het een veld is waar je verder conclusies uit gaat trekken gebaseerd op vergelijkingen met andere datum/tijd, berekeningen maken, sorteren enz, dan zie je de problemen al opduiken nog voor je op pensioen* bent. En timestamp is ook zuiniger met opslagruimte.
(* bv als je geboren bent na de default pc BIOS datum van 04-01-1980)

DATETIME is dus het veiligere alternatief, maar let op met de tijdszone.
Timestamp probeert de “huidige” tijdszone om te zetten naar UTC om de waarde op te slaan in de database, en terug te zetten naar de tijdszone (van de server**) bij het opvragen.
** dus niet de zone van de client als je bv vanop afstand gegevens opvraagt

Tijdzone
Vanaf Gambas 3.18 kan de tijdzone meegegeven worden:
(Old date string representation) space [ UTC | GMT ] [ + | - ] HH [ :MM ]

Om de algehele verwarring rond datums, (interne) opslag en weergave, tijdzone en formaten aan te pakken werd deze wiki pagina gemaakt, met oa:

Datums zijn geen strings
– Interne voorstelling
– Functies die werken met U.T.C. en American date format
– Functies die werken met local time
– Impliciete omvorming
– Datums zijn getallen
Null datums en datums met alleen een tijdsdeel
– Datums bewaren
– Datums bewaren in een binair bestand
– Datums bewaren in een tekstbestand
– Datums en kalenders

Voor selectie van een datum, zie ook de wiki pagina over kalenders.

Bronnen
– mailinglist en bugtracker
https://lists.gambas-basic.org/pipermail/user/2018-May/064153.html
Datetimes versus timestamps in MySQL
https://gambaswiki.org/ wiki/doc/date, wiki/doc/calendar

Gambas compatibiliteit (backward compatibility): soms niet

Als je broncode schrijft in Gambas versie 3.(x) dan kan het zijn dat die niet werkt in versie 3.(x-1) https://gambaswiki.org/wiki/doc/compat
Als het een voorwaarde is dat die code daar wel werkt moet je weten wat niet gebruikt mag worden uit de mogelijkheden van je nieuwere Gambas versie.
Hieronder begin ik een lijstje met zelf ondervonden incompatibiliteit, als ik een officiële Gambas pagina vindt daarover komt die hier in de plaats…

Als je weet waar in je code het probleem ontstaat op de oude versie, kan je daar “TRY” gebruiken:
Use TRY and check for an ERROR to see if newer code will work on the current version of gambas or not.

Settings.Exist : code gemaakt in 3.18.4 – code werkt niet in: 3.9.1

with / end with : nesten van twee strukturen in elkaar werkt niet in oude Gambas versies.

with myClass
  with myObject
    ' code code..
  end with
end with

Form elementen : bepaalde eigenschap bestaat niet in oude versie/andere desktop (Gnome):
ScrollView.Autoresize

Speak met Gambas3

Als uitbreiding op Spreken met Linux kan je er ook nog Gambas tussensteken. M.a.w. espeak aanroepen vanuit je eigen Gambas3 programma. Een testprogramma bijeenharken is niet nodig, dat deed Charlie Ogier al voor ons: eSpeakGUI

Simple text to speech GUI for ‘eSpeak’
Updated for QT5 22/03/2021

Naast in te stellen opties voor toonhoogte, woordafstand enz, is het belangrijkste commando doorgegeven via shell:

Shell "espeak -v " & sList[ComboBoxAccent.Index] &
" -a " & SpinBoxAmplitude.Value & " -g " &
SpinBoxWordGap.Value & " -p " & SpinBoxPitch.Value &
" -s " & SpinBoxSpeed.Value & " " & Chr(34) &
TextEditor1.Text & Chr(34)

Charlie Ogier (C) 2016 – Licenced under GPL 3.0

chr(34) is blijkbaar een ” teken.
sList is een array van strings die staan voor de talen* (ikzelf zou het arrsAccents noemen)
(* die in een combobox worden geladen om te laten kiezen)

Public sList As String[] = ["en", "en-gb", "en-uk-north", "en-sc", "en-wmids", "en-us", "en-wi"] 'String for Accent type"

" -a " & SpinBoxAmplitude.Value ‘ de amplitude: luider/zachter
" -g " & SpinBoxWordGap.Value lengte van de rust tussen de woorden
" -p " & SpinBoxPitch.Value toonhoogte
" -s " & SpinBoxSpeed.Value snelheid

Ik ben wel vergeten waar ik het vandaan heb.
Ik heb hem teruggvonden op github : https://github.com/charlie-ogier/eSpeakGUI

Gambas2 in 2023?

Gambas2 draait nog steeds op een computer(*) met OpenSUSE (mogelijk geïnstalleerd in 2015), altijd ge-update werd en die ondertussen natuurlijk ook gambas3 heeft.

(*) Ondertussen aan:

Waarschijnlijk oorspronkelijk openSUSE 15.0 of Leap 42.3/42.1/13.2/13.1/23.3… maar misschien wel eens een nieuwe installatie gedaan over de oude ipv een update..

Hoe oud/wanneer oorspronkelijk geïnstalleerd?
In ieder geval Yast log files van 2021, 2020, 2019, 2017 (13/11/2017)

head zypp/history
2017-11-13 11:08:48|command|root@mybox|'/usr/bin/ruby' '/usr/lib/YaST2/bin/y2start' 'installation' '--arg' 'initial' 'qt' '--noborder' '--auto-fonts' '--fullscreen'|

rpm -qa --last | tail -1
gpg-pubkey-307e3d54-4be01a65 ma 13 nov 2017 11:08:47

stat /
Bestand: /
Grootte: 156 Blokken: 0 IO-blok: 4096 map
Apparaat: 2fh/47d Inode: 256 Koppelingen: 1
Toegang: (0755/drwxr-xr-x) UID: ( 0/ root) GID: ( 0/ root)
Toegang: 2023-03-22 09:14:57.697958271 +0100
Gewijzigd: 2018-11-26 08:18:02.931829791 +0100
Veranderd: 2018-11-26 08:18:02.931829791 +0100
Ontstaan: 2017-11-13 11:08:43.728015653 +0100

(dan zou het normaal een Leap 42.1 moeten geweest zijn).

Zeker:
OpenSUSE 15.4 (2023-02-22) : gambas2 : ok
OpenSUSE 15.3 (2022-?-? ) : gambas2 : ok
OpenSUSE 15.2 2021-06-23 : gambas2 : ok
(..?..)

HSplit werkt niet meer

Gordijn kapot
Bij de laatste upgrade van mijn Linux+KDE systeem en bijhorende Gambas (naar 3.18.0), werkte één van mijn programma’s niet meer naar behoren. De verdeling van de gebieden op het scherm die met een HSplit van elkaar gescheiden zijn, zijn getroffen door een “bug”. Die HSplit werkt als een soort gordijn, je kan die vertikale lijn tussen twee gebieden “in de HSplit” vastnemen en naar links of naar rechts trekken, zodat een bepaald gebied vergroot en het andere automatisch verkleint.

Ik heb een aantal gridviews in de HSplit, en tot nu toe werkte dat perfect. Maar na die update gebeuren er eigenaardige dingen; als ik een vertikale lijn wil opschuiven naar links bv, verandert de vertikale lijn van een andere gridview van plaats op het scherm. Het lijkt of je een andere lijn vasthebt bij het verschuiven, bv de volgende splitter lijn.

Buiten gebruik?
In het menu valt me ook op dat de “HSplit” niet meer voorkomt, wel een “Splitter”.
Als ik een bestaande HSplit selecteer zie ik er een symbool van doorstreepte cirkel op staan, en krijg ik geen eigenschappen rechts. Voelt erg “depricated”? Maar daar wordt niets van vermeld op http://gambaswiki.org/wiki/comp/gb.qt4/vsplit.

Ik vind wel een verwijzing in de mailinglist:

Re: [Gambas-user] Unnecessary duplication?
User namens
Bruce Steers 27-06-2022
Naar Gambas Mailing List


It’s rare to actually remove anything. many things are depreciated like for example HSplit and VSplit changed to one single Splitter container but VSplit and HSplit are not gone and still work for programs using it.

Daaruit leid ik af dat ik de HSplit en de VSplit moet vervangen door “Splitter“. Aangezien Splitter algemener is zal je moeten aangeven wat de richting is (H/V).

Backward (in)compatible
En ook omgekeerd ondervind je problemen: als je met 3.14 een project opent van 3.18 waarin de nieuwe Splitter gebruikt wordt, krijg je een foutmelding.

ProjectName > Sources > FormName
Cannot open file.
Unknown control: Splitter

Daar kan je verder dan niet veel aan doen op dit systeem…

HSplit Parameters
Verder lijkt er ook iets foutgegaan te zijn met de parameters van het bewaren van de HSplit instellingen:

Hoe moet het nu juist? Hoe kan ik “compatibele” code maken voor 3.14?
'Try HSplit1.Settings = ["150,120,600,300,160"]
Try HSplit1.Settings = [150, 120, 600, 300, 160]
'Splitter1.Settings = Settings["Screen/Splitter", "150,600,300,160"]

In het settings bestand vind ik verschillende sporen:
Splitter="0,188,977,131,276"
Splitter.Layout=[189,283,364,562,0]

(wordt vervolgd als ik daar problemen mee ondervind)

Data naar Arduino sturen via USB kabel

De usb kabel die je gebruikt om het programma in de arduino te laden kan je ook gebruiken om data door te sturen, bv vanuit Gambas.

Je moet het seriële poort object gebruiken, waarvoor je de gb.net bibliotheek importeert (Project eigenschappen, libraries).

Variabele declareren:

Public hSerial As SerialPort

Initialiseren van het object:

hSerial = New SerialPort As "hSerial"

(ps: AS "hSerial" wordt later gebruikt om te lezen van de poort)

Eigenschappen instellen:

  With hSerial
    .Clear
    .PortName = "/dev/ttyUSB0"
    .Speed = 9600 ' 4800
    .DataBits = SerialPort.Bits8
    .StopBits = SerialPort.Bits1
    .Parity = SerialPort.None
    .FlowControl = SerialPort.None
    .Clear
  End With

Poort openen:

Try hSerial.Open(3)
  If Error Then
    Print Error.Text
  Else 
    TSendTimer.Start()
  Endif 

Ik heb een timer gemaakt om gemakkelijk automatisch een aktie als een waarde uitsturen te laten uitvoeren:

Public TSendTimer As Timer
  '
  Try iNumber = getSomeValueFromDb()
  If Error Then
    Print Error.Text
  Else 
    If iNumber <> iPrevious
      doSend(iNumber)
      iPrevious = iNumber
    Else 
      ' 
    Endif 
  Endif

(in hetzelfde programma heb ik een andere timer voor het lezen van de seriële poort)

De timer aktiveert het ophalen van de gegevens van elders, bv uit een database:

getSomeValueFromDb() kan je vervanen door eender welke bewerking voor het ophalen van een waarde uit een databank, een bewerking, uitlezen van menselijke invoer, enz..

En het uisturen van de klaarstaande gegevens:


Public Sub doSend(iNumber As Integer)
'  
  Debug Now() & " Gb3 doSend > " & iNumber
  Try Write #hSerial, Str(iNumber) & gb.NewLine
  If Error Then
    Print "Gb3 Err: " & Error.Text
  Else 
    hSerial.Send()
    Inc iCounter
  Endif 

Ik hou wat tellers bij en toon in het konsole scherm de waarden die heen en weer gaan tussen de arduino en de Raspberry Pi/pc, daarom dat ik ze laat voorafgaan door “Gb3” om aan te geven wat de bron is. De inkomende data van de arduino toon ik daar immers ook.

Ontvangen via dezelfde weg

Instellen:

Public Sub setReceive()
'  
  Debug "Gb3: setReceive"
  With hSerial
    If .Status = Net.Active Then
      TTimer.Start()
      Print .DTR
      Print .DSR
      Print .Blocking
      Print .CTS
      Print .RTS
    Endif
  End With
  '
End

Lezen van seriële poort:

Public Sub hSerial_Read()
  '
  Try Read #hSerial, sIn, Lof(hSerial)
  '
End

De timer voor ontvangen van data:

Public Sub TTimer_Timer()
'
  If hSerial.Status <> Net.Active Or If sIn = "" Then 
    ' Print "Gb3: No data, or empty string.."
  Else 
    If sIn <> sPrevious
      Print "Gb3: Data received: " & sIn
      sPrevious = sIn
    Endif 
  Endif
  '
End