I want to use a sqlite3 database at my ESP8266 NodeMCU microproessor.
The firmware is:
NodeMCU custom build by frightanic.com
branch: master
commit: 67027c0d05f7e8d1b97104e05a3715f6ebc8d07f
SSL: false
modules: bit,bme280,cron,dht,file,gpio,i2c,net,node,rfswitch,rtctime,sntp,sqlite3,tmr,uart,wifi
build created on 2018-04-16 16:06
powered by Lua 5.1.4 on SDK 2.2.1(cfd48f3)
The (main part) of the code I use is:
(The complete code follows later at this post)
-- Wenn Tabelle nicht exisiert, ohne Daten anlegen
sql = "CREATE TABLE IF NOT EXISTS '"..tabelle.."' ('"..lokal.."' number,'"..sntp.."' number)"
status = db:exec(sql)
print(sql)
print("Status Anlage '"..tabelle.."': ",status)
The log is:
> -- drop_sntptab()
> existenzsicherung_sntptab()
E:M 4272
CREATE TABLE IF NOT EXISTS 'abgleich' ('lsync' number,'ssync' number)
Status Anlage 'abgleich': 7
SELECT count(*) FROM 'abgleich'
no such table: abgleich
You see, the table is not created althougt the SQL-Statement seems to be right.
The opening command is:
db = sqlite3.open(database)
Find following the complete Script:
database = 'sntp.db'
tabelle = 'abgleich'
lokal = 'lsync'
sntp= 'ssync'
l0 = 1514764800 -- Epoche-Time 01.01.2018 00:00:00
s0 = 1514764800 -- Epoche-Time 01.01.2018 00:00:00
function open_db()
-- Datenbankdatei allokieren
db = sqlite3.open(database)
end
function close_db()
status = db:close()
print("Status DB-schliessen: ", status)
end
function delete_sntp_database()
-- Datenbankdatei wird geloescht
file.remove(database)
end
function drop_sntptab()
--- Tabelle loeschen
sql = "DROP TABLE '"..tabelle.."';"
status = db:exec(sql)
print(sql)
print("Status DROP "..tabelle..": ",status)
end
function existenzsicherung_sntptab()
-- Wenn Tabelle nicht exisiert, ohne Daten anlegen
sql = "CREATE TABLE IF NOT EXISTS '"..tabelle.."' ('"..lokal.."' number,'"..sntp.."' number)"
status = db:exec(sql)
print(sql)
print("Status Anlage '"..tabelle.."': ",status)
-- Anzahl der Datenaetze ermitteln
sql = "SELECT count(*) FROM '"..tabelle.."'"
print(sql)
for tmp in db:urows(sql)
-- Anzahl Datensätze
do
anzahl = tmp
end
print('Anzahl Datensaetze: ',anzahl)
-- Wenn Anzahl der Datensätze 0 ist, wird eine Datenzeile eingefügt
if anzahl == 0
then
sql = "INSERT INTO '"..tabelle.."' ('"..lokal.."', '"..sntp.."') values ("..l0..","..s0..")"
status = db:exec(sql)
print(sql)
print("Status Eingabe Feldwerte: ",status)
end
-- Ausgabe des Tabelleninhalts
-- urows ermöglicht die Zeilenweise Ausgabe des Select - Ergebnis
sql = "SELECT * FROM '"..tabelle.."'"
for lokal,sntp in db:urows(sql)
do
print(lokal,sntp)
end
end
function ermittel_lastlokal()
sql = "SELECT * FROM '"..tabelle.."' WHERE _ROWID_ = 1;"
for v1,v2 in db:urows(sql)
do
print("Ergebniszeile(n): ",v1,v2)
lastlokal = v1
lastsntp = v2
end
end
-- delete_sntp_database()
open_db()
-- drop_sntptab()
existenzsicherung_sntptab()
-- ermittel_lastlokal()
close_db()
Can anyone see my mistake?
Thank you very much in advance
Regards
Kleinlaut
Related
I have the below PeopleCode step in an Application Engine program that reads a CSV file using a File Layout and then inserts the data into a table, and I am just trying to get a better understanding of how the the line of code (&SQL1 = CreateSQL("%Insert(:1)");) in the below script gets generated. It looks like the CreateSQL is using a bind variable (:1) inside the Insert statement, but I am struggling as where to find where this variable is defined in the program.
Function EditRecord(&REC As Record) Returns boolean;
Local integer &E;
&REC.ExecuteEdits(%Edit_Required + %Edit_DateRange + %Edit_YesNo + %Edit_OneZero);
If &REC.IsEditError Then
For &E = 1 To &REC.FieldCount
&MYFIELD = &REC.GetField(&E);
If &MYFIELD.EditError Then
&MSGNUM = &MYFIELD.MessageNumber;
&MSGSET = &MYFIELD.MessageSetNumber;
&LOGFILE.WriteLine("****Record:" | &REC.Name | ", Field:" | &MYFIELD.Name);
&LOGFILE.WriteLine("****" | MsgGet(&MSGSET, &MSGNUM, ""));
End-If;
End-For;
Return False;
Else
Return True;
End-If;
End-Function;
Function ImportSegment(&RS2 As Rowset, &RSParent As Rowset)
Local Rowset &RS1, &RSP;
Local string &RecordName;
Local Record &REC2, &RECP;
Local SQL &SQL1;
Local integer &I, &L;
&SQL1 = CreateSQL("%Insert(:1)");
rem &SQL1 = CreateSQL("%Insert(:1) Order by COUNT_ORDER");
&RecordName = "RECORD." | &RS2.DBRecordName;
&REC2 = CreateRecord(#(&RecordName));
&RECP = &RSParent(1).GetRecord(#(&RecordName));
For &I = 1 To &RS2.ActiveRowCount
&RS2(&I).GetRecord(1).CopyFieldsTo(&REC2);
If (EditRecord(&REC2)) Then
&SQL1.Execute(&REC2);
&RS2(&I).GetRecord(1).CopyFieldsTo(&RECP);
For &L = 1 To &RS2.GetRow(&I).ChildCount
&RS1 = &RS2.GetRow(&I).GetRowset(&L);
If (&RS1 <> Null) Then
&RSP = &RSParent.GetRow(1).GetRowset(&L);
ImportSegment(&RS1, &RSP);
End-If;
End-For;
If &RSParent.ActiveRowCount > 0 Then
&RSParent.DeleteRow(1);
End-If;
Else
&LOGFILE.WriteRowset(&RS);
&LOGFILE.WriteLine("****Correct error in this record and delete all error messages");
&LOGFILE.WriteRecord(&REC2);
For &L = 1 To &RS2.GetRow(&I).ChildCount
&RS1 = &RS2.GetRow(&I).GetRowset(&L);
If (&RS1 <> Null) Then
&LOGFILE.WriteRowset(&RS1);
End-If;
End-For;
End-If;
End-For;
End-Function;
rem *****************************************************************;
rem * PeopleCode to Import Data *;
rem *****************************************************************;
Local File &FILE1, &FILE3;
Local Record &REC1;
Local SQL &SQL1;
Local Rowset &RS1, &RS2;
Local integer &M;
&FILE1 = GetFile("\\nt115\apps\interface_prod\interface_in\Item_Loader\ItemPriceFile.csv", "r", "a", %FilePath_Absolute);
&LOGFILE = GetFile("\\nt115\apps\interface_prod\interface_in\Item_Loader\ItemPriceFile.txt", "r", "a", %FilePath_Absolute);
&FILE1.SetFileLayout(FileLayout.GH_ITM_PR_UPDT);
&LOGFILE.SetFileLayout(FileLayout.GH_ITM_PR_UPDT);
&RS1 = &FILE1.CreateRowset();
&RS = CreateRowset(Record.GH_ITM_PR_UPDT);
REM &SQL1 = CreateSQL("%Insert(:1)");
&SQL1 = CreateSQL("%Insert(:1)");
/*Skip Header Row: The following line of code reads the first line in the file layout (the header)
and does nothing. Then the pointer goes to the next line in the file and starts using the
file.readrowset*/
&some_boolean = &FILE1.ReadLine(&string);
&RS1 = &FILE1.ReadRowset();
While &RS1 <> Null
ImportSegment(&RS1, &RS);
&RS1 = &FILE1.ReadRowset();
End-While;
&FILE1.Close();
&LOGFILE.Close();
The :1 is coming from the line further down &SQL1.Execute(&REC2);
&REC2 gets assigned a record object, so the line &SQL1.Execute(&REC2); evaluates to %Insert(your_record_object)
Here is a simple example that's doing basically the same thing
Here is a description of %Insert
Answer because too long to comment:
The table name is most likely (PS_)GH_ITM_PR_UPDT. The general consensus is to name the FileLayout the same as the record it is based on.
If not, it is defined in FileLayout.GH_ITM_PR_UPDT. Open the FileLayout, right click the segment and under 'Selected Node Properties' you will find the 'File Record Name'.
In your code this record is carried over into &RS1.
&FILE1.SetFileLayout(FileLayout.GH_ITM_PR_UPDT);
&RS1 = &FILE1.CreateRowset();
The rowset is a collection of rows. A row consists of records and a record is a row of data from a database table. (Peoplesoft Object Data Types are fun...)
This rowset is filled with data in the following statement:
&RS1 = &FILE1.ReadRowset();
This uses your file as input and outputs a rowset collection, mapping the data to records based on how you defined your FileLayout.
The result is fed into the ImportSegment function:
ImportSegment(&RS1, &RS);
Function ImportSegment(&RS2 As Rowset, &RSParent As Rowset)
&RS2 in the function is a reference to &RS1 in the rest of your code.
The table name is also hidden here:
&RecordName = "RECORD." | &RS2.DBRecordName;
So if you can't/don't want to check the FileLayout, you could output &RS2.DBRecordName with a messagebox and your answer will be Message Log of your Process Monitor.
Finally a record object is created for this database table and it is filled with a row from the rowset. This record is inserted into the database table:
&REC2 = CreateRecord(#(&RecordName));
&RS2(&I).GetRecord(1).CopyFieldsTo(&REC2);
&SQL1 = CreateSQL("%Insert(:1)");
&SQL1.Execute(&REC2);
TLDR:
Table name can be found in the FileLayout or output in the ImportSegment Function as &RS2.DBRecordName
We have installed Data Studio 4.1.0.0 Client to access the data that is stored in DB2. We have installed DB2 11.1 64bit on our PC which has a Windows 7 64 bit.
I need to connect to the DB2 data from 64bit R.
We tried the following
library (RODBC)
driver.name <- "{IBM DB2 ODBC DRIVER}"
db.name <- "SBXSHRD"
host.name <- "XX.XXX.X.XX"
port <- "60012"
user.name <- "X20XX4"
pwd <- "SXXXXX01"
#Connection String
con.text <- paste ("DRIVER =", driver.name,
"; Database =", db.name,
"; Hostname =", host.name,
"; Port =", port,
"; PROTOCOL = TCPIP",
"; UID =", user.name,
"; PWD =", pwd, sep = "")
#Connect to DB2
con1 <- odbcDriverConnect (con.text)
top <- sqlQuery (con1,
"SELECT *
FROM ODS_CANALES_LINK.VW_OP_D_TRANSACCIONCANAL
where CODMES_PROC = 201708
FETCH FIRST 3 ROW ONLY
",
errors = FALSE)
But I get the following result in r
> con1 <- odbcDriverConnect(con.text)
Warning messages:
1: In odbcDriverConnect(con.text) :
[RODBC] ERROR: state IM004, code 0, message [Microsoft][Administrador de controladores ODBC] Error de SQLAllocHandle del controlador en SQL_HANDLE_ENV
2: In odbcDriverConnect(con.text) : ODBC connection failed
here a detail of the DB2 that we have and a snapshot of what we are doing in R
enter image description here
enter image description here
RJDBC works quite well. But ... On one occasion, after the complete rebuild of docker image, I got all resultsets with changed column names because they changed name from jdbc function getColumnName to getColumnLabel.
https://github.com/s-/RJDBC/commit/7f1c1eec25ed90ec5ed71141189b816e2a3c2657
library(RJDBC)
CONSTR <- "jdbc:db2://hostname:446/database"
jcc = JDBC("com.ibm.db2.jcc.DB2Driver", "db2jcc4.jar")
connect <- function() {
dbConnect(jcc, CONSTR, user="scott", password="tiger")
}
dept <- function() {
con <- connect()
sql <- "SELECT DEPTNO, DEPTNAME FROM DSN8710.dept"
rs <- dbSendQuery(con, sql)
x <- dbFetch(rs)
dbClearResult(rs)
# change column names, because the names are not stable!
names(x) <- c('DEPTNO', 'DEPTNAME')
dbDisconnect(con)
x
}
I could use some help performing a database correction, in regards to date and time of pictures were taken.
Essentially, the research we perform entails taking many pictures and entering the picture information into a database (we automated this with Microsoft Access). However, I performed a random check of our database and found that several dates and times of the photos were incorrect, and I am attempting to correct this via R as I was unable to correct it via Access.
What I need to do is to is write a script that reads these data, and compiles a list of the date taken information for all photos (there are several thousand). So far the best thing that I've found is
file.info(list.files(
"E:/Whatcom Creek Project/Data/Seal photos/Discovery/Catalog/Phoca vitulina",
recursive = T))
However this returns a list of NA NA for all information. Also, if I manually select one image to run file.info on, it doesn't return date taken (see the picture for the data I am attempting to retrieve)
If anyone has any suggestions I am all ears. Thanks in advance!!
-Ian
enter image description here
maybe still of any use?
i saw this message. I solved this a long time ago (2011) with a very basic VB6 code. The job is still working, but it is not applicable to all '.jpg files'. It depends with what camera the picture has been taken, but mostly pictures taken from a smartphone and classic camera's are returning the date the picture has been taken (not usable for whatsapp images or edited images).
The code is here below, and it is very basic code (but i hope it still can help or give idea's, and ... any new idea's are welcome too) :
'Reading of "Date Picture Taken" from .jpg file
'-----------------------------------------------
Debug.Print ">>>>>==== Start Read of .jpg-file ===== "; Date; " ===== "; Time; " ====<<<<<"
X = 0
DatePictureTaken = ""
TimePictureTaken = ""
FOUNDdatum = False
SWdatum = False
TELdatum = 0
Foto = FOLDER & "\" & tabFileName(FotoNr)
Open Foto For Binary Access Read As #1
'get startposition of the field "date picture taken"
Do
X = X + 1
Get #1, X, MyByte ': Debug.Print Chr(MyByte);
DoEvents
If Chr(MyByte) = ":" Then
'Debug.Print
SWdatum = True
Get #1, X + 3, MyByte
'Debug.Print "x+03="; Chr(MyByte)
If Chr(MyByte) <> ":" Then SWdatum = False 'Debug.Print "x+03="; Chr(MyByte)
Get #1, X + 9, MyByte
'Debug.Print "x+09="; Chr(MyByte)
If Chr(MyByte) <> ":" Then SWdatum = False 'Debug.Print "x+09="; Chr(MyByte)
Get #1, X + 12, MyByte
'Debug.Print "x+12="; Chr(MyByte)
If Chr(MyByte) <> ":" Then SWdatum = False 'Debug.Print "x+12="; Chr(MyByte)
'if a ':' is on the 3 locations (found above) then it is a date!
If SWdatum _
Then
TELdatum = TELdatum + 1
End If
'the 3e date is the date the picture has been taken
If TELdatum = 3 _
Then
FOUNDdatum = True
X = X - 4
Exit Do
End If
X = X + 12
End If
Loop Until EOF(1) 'Or X = 32765
If FOUNDdatum = False Then Close 1: End
BPdatum = X
EPdatum = X + 9
BPuur = X + 11
EPuur = X + 15
For X = BPdatum To EPdatum
Get #1, X, MyByte
'Debug.Print Chr(MyByte)
If Chr(MyByte) <> ":" _
Then
' DatePictureTaken = DatePictureTaken & "/"
'Else
DatePictureTaken = DatePictureTaken & Chr(MyByte)
End If
Next X
For X = BPuur To EPuur
Get #1, X, MyByte
'Debug.Print Chr(MyByte)
If Chr(MyByte) <> ":" _
Then
' DatePictureTaken = DatePictureTaken & "/"
'Else
TimePictureTaken = TimePictureTaken & Chr(MyByte)
End If
Next X
'Debug.Print "Date Picture Taken = "; DATUM
tbxDatum.Text = DatePictureTaken
tbxUur.Text = TimePictureTaken
Close 1
End Sub
I am currently monitoring multiple systems' OS (Unix) filesystem utilization and DB (Sybase) utilization. I would like to query those in one file using the vi editor. My script goes like this:
df -h
su - sybpg1
isql -Usapsa -SPG1 -PMaster4SID -w999 -X
declare #pagesize numeric(19,0)
select #pagesize=(select ##maxpagesize)
SELECT "Database Name" = CONVERT(char(30), db_name(D.dbid)),
"Data Size MB" = STR(SUM(CASE WHEN U.segmap != 4 THEN U.size*#pagesize/1048576 END),10,1),
"Used Data MB" = STR(SUM(CASE WHEN U.segmap != 4 THEN size - curunreservedpgs(U.dbid, U.lstart, U.unreservedpgs)END)*#pagesize/1048576,10,1),
"Data Full%" = STR(100 * (1 - 1.0 * SUM(CASE WHEN U.segmap != 4 THEN curunreservedpgs(U.dbid, U.lstart, U.unreservedpgs) END)/SUM(CASE WHEN U.segmap != 4 THEN U.size END)),9,1) ,
"Log Size MB" = STR(SUM(CASE WHEN U.segmap = 4 THEN U.size*#pagesize/1048576 END),10,1),
"Free Log MB" = STR(lct_admin("logsegment_freepages",D.dbid)*#pagesize/1048576,10,1),
"Log Full%" = STR(100 * (1 - 1.0 * lct_admin("logsegment_freepages",D.dbid) /
SUM(CASE WHEN U.segmap = 4 THEN U.size END)),8,1)
FROM master..sysdatabases D,
master..sysusages U
WHERE U.dbid = D.dbid
AND ((D.dbid != 2))
GROUP BY D.dbid
ORDER BY db_name(D.dbid)
go
but whenever i execute:
sh filename
It was able to enter sybase, however couldn't get pass through the isql line.
It goes something like this:
sybsid.sh: line 6: isql: command not found
Hope you could help me out.
Thanks!
I want to get the name of the zone, the number of products and the denomination of the product with the minimal stock order by the name of the zone.
I got almost everything except the denomination which prints nothing.
My code:
for $zone in distinct-values(/productos/produc/cod_zona)
let $numero := count(/productos/produc[cod_zona = $zone]/cod_prod)
let $nomzona:=/zonas/zona[cod_zona = $zone]/nombre
let $minimo :=min(/productos/produc[cod_zona = $zone]/stock_minimo)
let $deno :=/productos/produc[stock_minimo=$minimo]/denominacion
order by $nomzona ascending
return concat( 'Zona:', $nomzona,' ',
'Productes:', $numero,' ',
'Mínim stock:', $deno
The result:
Zona:Andalucía Productes:2 Mínim stock: //here must be print like that "Placa base "
Zona:Extremadura-Galicia Productes:3 Mínim stock:
Zona:Levante-Cataluña Productes:4 Mínim stock:
Zona:Madrid-CENTRO Productes:4 Mínim stock:
productos.xml:
<productos>
<TITULO>DATOS DE LA TABLA PRODUCTOS</TITULO>
<produc>
<cod_prod>1010</cod_prod>
<denominacion>Placa Base MSI G41M-P26</denominacion>
<precio>50</precio>
<stock_actual>10</stock_actual>
<stock_minimo>3</stock_minimo>
<cod_zona>10</cod_zona>
</produc>
<produc>
<cod_prod>1011</cod_prod>
<denominacion>Micro Intel Core i5-2320</denominacion>
<precio>120</precio>
<stock_actual>3</stock_actual>
<stock_minimo>5</stock_minimo>
<cod_zona>10</cod_zona>
</produc>
<produc>
<cod_prod>1012</cod_prod>
<denominacion>Micro Intel Core i5 2500</denominacion>
<precio>170</precio>
<stock_actual>5</stock_actual>
<stock_minimo>6</stock_minimo>
<cod_zona>20</cod_zona>
</produc>
<produc>
<cod_prod>1013</cod_prod>
<denominacion>HD Seagate Barracuda 250GB SATA</denominacion>
<precio>80</precio>
<stock_actual>10</stock_actual>
<stock_minimo>5</stock_minimo>
<cod_zona>20</cod_zona>
</produc>
<produc>
the other xml:
zonas.xml:
<zonas>
<TITULO>DATOS DE LA TABLA ZONAS</TITULO>
<zona>
<cod_zona>10</cod_zona>
<nombre>Madrid-CENTRO</nombre>
<director>Pedro Martín</director>
</zona>
<zona>
<cod_zona>20</cod_zona>
<nombre>Extremadura-Galicia</nombre>
<director>Alicia Pérez</director>
</zona>
<zona>
What am I doing wrong?
Thanks/Gracias/Merci
You are not restricting $deno to the current zone, so for producs with the same stock_minimo, this will return a sequence instead of an single item. So you should first add another predicate for zone:
let $deno := /productos/produc[cod_zona = $zone][stock_minimo=$minimo]/denominacion
However, if there were ever two produc in the same zone with the same min(stock_minimo), you will have the same problem, so you can plan for this in your output by using string-join instead of concat:
concat( 'Zona:', $nomzona,' ',
'Productes:', $numero,' ',
'Mínim stock:', string-join($deno, ', ') ...