How to store/change a hostname in ESP32 without reprogramming - esp32

I was planning to change the code for the khoi-prog ESP_WiFiManager to add a hostname field to the configuration form.
I've already modified the form to support an optional field:
#ifdef CONFIG_HOSTNAME
const char WM_HTTP_FORM_START[] PROGMEM =
"`<`form method='get' action='wifisave'`>``<`fieldset`>``<`div`>``<`label`>`Hostname`<`/label`>``<`input id='h' name='h' length=32 "
"placeholder='Hostname'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`SSID`<`/label`>``<`input id='s' name='s' length=32 "
"placeholder='SSID'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`Password`<`/label`>``<`input id='p' name='p' length=64 "
"placeholder='password'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`SSID1`<`/label`>``<`input id='s1' name='s1' length=32 "
"placeholder='SSID1'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`Password`<`/label`>``<`input id='p1' name='p1' length=64 "
"placeholder='password1'`>``<`div`>``<`/div`>``<`/div`>``<`/fieldset`>`";
#else
const char WM_HTTP_FORM_START[] PROGMEM =
"`<`form method='get' action='wifisave'`>``<`fieldset`>``<`div`>``<`label`>`SSID`<`/label`>``<`input id='s' name='s' length=32 "
"placeholder='SSID'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`Password`<`/label`>``<`input id='p' name='p' length=64 "
"placeholder='password'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`SSID1`<`/label`>``<`input id='s1' name='s1' length=32 "
"placeholder='SSID1'`>``<`div`>``<`/div`>``<`/div`>``<`div`>``<`label`>`Password`<`/label`>``<`input id='p1' name='p1' length=64 "
"placeholder='password1'`>``<`div`>``<`/div`>``<`/div`>``<`/fieldset`>`";
#endif
Next to do was store the information in EEPROM but the "wifi_ap_record_t" structure that holds ssid and pwd, leaves no place to do that.
Does anybody have any idea where to leave this information in the ESP?
Can I just drop it somewhere in SPIFFS or EEPROM or will that bite me sometime in the future when I use EEPROM for another purpose. I've used EEPROM a few times before, but never inside a library.
Hope this is at all possible.

Related

JACoP Colocalization Macro Errors Galore

I've tried countless combinations of paths to try and get my macro working to analyze a very large set of images using JACoP. Any suggestions on what might be the issue?
this iteration got me closest (I think) to getting it to work. It even loads images, as shown in attached photos, but won't actually analyze the images themselves. Im thinking it might have something to do with me improperly setting up the loop to repeat itself? also maybe I'm designating channels incorrectly? pretty lost on what to do next, and there aren't any answers I've found on the web.
## File (label = "Input directory", style = "directory") input
## File (label = "Output directory", style = "directory") output
## String (label = "File suffix", value = ".nd2") suffix
// See also Process_Folder.py for a version of this code
// in the Python scripting language.
input = "/Users/alexandrapowell/Desktop/221223B31A3/"
output = "/Users/alexandrapowell/Desktop/221223B31A3batchh/"
processFolder(input);
// function to scan folders/subfolders/files to find files with correct suffix
function processFolder(input) {
list = getFileList(input);
fileList = Array.sort(list);
for (i = 0; i < list.length; i++) {
if(File.isDirectory(input + File.separator + list[i]))
processFolder(input + File.separator + list[i]);
if(endsWith(list[i], suffix))
processFile(input, output, list[i]);
}
}
function processFile(input, output, file) {
open(list[i])
run("JACoP ", "imga=0 imgb=1 thra=15000 thrb=3000 get_pearsons get_manders get_overlap");
// Do the processing here by adding your own code.
// Leave the print statements until things work, then remove them.
print("Processing: " + input + File.separator + file);
saveAs("Text", output + File.separator + "_coloc.txt")
print("Saving to: " + output);
run("Close");
run("Close All");
}

How to send color images with ESC/POS?

I have an Epson CW-C6000 that I'm trying to control with ESC commands. I've gotten text to print, so I know I have the IP address, port, etc correct but cannot for the life of me get an image printed.
Here is my code (running from a Ruby on Rails server, with most of the image truncated):
streamSock = TCPSocket.new( "X.X.X.X", 9100 )
str = "~DYR:PRODIMG,B,P,183208,0,89504E470D...4AE426082" + "^XA" + "^FO150,150^IMR:PRODIMG.PNG^FS" + "^XZ"
streamSock.send( str , 0)
streamSock.close
The image is a .png I converted to hexadecimal with this site:
http://tomeko.net/online_tools/file_to_hex.php?lang=en
I'm mostly using page 10 of this PDF for reference:
https://files.support.epson.com/pdf/pos/bulk/esclabel_apg_en_forcw-c6000series_reve.pdf
Does anyone have a hint? Epson support staff was spectacularly unhelpful.
Also I'm sorry if my formatting is bad; I'm new here and will happily edit my post if something is wrong.
Alright I finally got it working. The command for printing a color .PNG is this:
~DYE:[Image Name].PNG,p,p,[Image Size],0,:B64:[Base64 String]:[CRC]
Things that tripped me up:
-You seem to need the .PNG extension on the file name, even though the Epson manual doesn't show that.
-[Image Size] is the number of characters in the Base64 string, even though the Epson manual says it should be the size of the original .PNG image file. If this is wrong the printer will hang and no longer accept input of any kind until restarted.
-There may be other options, but I could only get it working with a CRC of the hex CRC-16/XMODEM type.
Thanks to K J for his/her suggestions and coming along with me!
Perhaps this material can be used as an additional reference.
They seem to have a completely different command/data format than ESC/POS.
ESC/Label Command Reference Guide
Page 12
1.3.4 About Saving the Graphics and Label Formats in the Printer
With ESC/Label command, you can save graphics and label formats in the printer. The printer has a file system. Data saved in the printer is handled as files and is managed in the following way.
The file system does not have a hierarchy.
The printer has a non-volatile saving device, such as Flash ROM, and a volatile saving device, such as RAM, and different drive letters are allocated for each device.
Files are designated as
"<drive letter> colon <:> <file name> dot <.> <extension>".
Page 40-41
2.8 Printing Graphics
...Details have been omitted. Please refer to the actual document...
2.8.1 Registering a Graphic in a Printer and Printing It
...Pick up some from the content. Please refer to the actual document...
Delete the files that remain in the printer (^ID command).
Register the graphic in the printer (~DY command).
When registering a color graphic, you can use the PNG format. When registering a monochrome graphic, you can register the PNG format or the GRF format.
PNG format Monochrome and color graphics
GRF format Monochrome graphics
The reason to execute the step 1.
To ensure capacity of the storage memory necessary for print which application will perform.
2.8.2 Embedding a Graphic in the Field and Printing It
...Details have been omitted. Please refer to the actual document...
In Addition:
Page 104-106
~DY
[Name]
Save File
[Format]
~DY d: o ,f ,x ,t ,w ,data
...A table detailing the parameters is due, but omitted...
[Function]
...Further detailed explanations and figures of functions and parameters are due, but omitted...
Graphic data is handled as follows.
If the data format is binary, you can use any binary data as Parameter data. At this time, the size of Parameter data must be matched to the size specified in Parameter t.
If the data format is a hexadecimal character string, one character from 1. to 3. below is used as Parameter data. At this time, the size of Parameter data written in binary must be matched to the size specified in Parameter t.
0 to 9, A to F, and a to f in ASCII can be used as hexadecimal graphic data.
ASCII comma <,>, the parameter separator character, is used to separate lines. If a comma is input, processing is carried out as if ASCII 0 was input for the remainder of the line.
G to Y and g to z in ASCII can be used as repetition characters. For example, if I9 is input, processing is carried out as if 999 were input. The following table indicates the number of repetitions.
...Characters and repeat specified number of times table omitted...
Looking at the contents of this Technical Reference Guide, it seems that you can register images with tools instead of commands.
CW-C6000/C6500 Series Technical Reference Guide
Page 173-174
And page 288 outlines the Epson Inkjet Label Printer SDK and also describes the existence of sample programs.
#Farmbot26. I have been attempting this same using vb.Net and as you noted Epson support is not helpful. I'm not sure if it's the actual image data that is wrong, CRC, or the ZPL code as nothing helps. Here's 2 examples that have not worked.
`Dim binaryData As Byte() = System.IO.File.ReadAllBytes(txtPNGFile.Text)
zplImageData = Convert.ToBase64String(binaryData)
crc = calcrc(binaryData, binaryData.Length).ToString("X4")
Dim zplToSend As String = "~DYE:" & Path.GetFileName(txtPNGFile.Text).ToUpper & ",P,P," & zplImageData.Length & ",0,:B64:" & zplImageData & ":" & crc & "^XZ"`
`Dim binaryData As Byte() = System.IO.File.ReadAllBytes(txtPNGFile.Text)
crc = calcrc(binaryData, binaryData.Length).ToString("X4") 'Calculate CRC
zplImageData = BitConverter.ToString(binaryData).Replace("-", "")
Dim zplToSend As String = "~DYE:" & Path.GetFileName(txtPNGFile.Text).ToUpper & ",A,P," & zplImageData.Length & ",0,:B64:" & zplImageData & ":" & crc & "^XZ"`
This is the CRC example I have.
`Function calcrc(ByVal data() As Byte, ByVal count As Integer) As Integer
Dim crc As Integer = 0
For Each b As Byte In data
Dim d As Integer = CInt(b)
crc = crc Xor (d << 8)
For j = 0 To 7
If ((crc And &H8000) <> 0) Then
crc = (crc << 1) Xor &H1021
Else
crc = (crc << 1)
End If
Next
Next
Return crc And &HFFFF
End Function`
I have figured out another solution. Save the PNG Image using the Binary data. I found this when reading the Saved Backup file of Image data using the Epson Settings Utility.
~DYE:FILENAME.PNG,B,P,BINARYFILESIZE,0, BINARYIMGDATA
` Try
Dim binaryData As Byte() = System.IO.File.ReadAllBytes(txtPNGFile.Text)
Dim client As System.Net.Sockets.TcpClient = New System.Net.Sockets.TcpClient()
client.Connect(IP_TextBox1.Text.Replace(" ", ""), txtPort.Text)
Dim writer As System.IO.StreamWriter = New System.IO.StreamWriter(client.GetStream(), Encoding.UTF8)
Using mStream As New MemoryStream(binaryData)
Dim zplToSend As String = "~DYE:" & Path.GetFileName(txtPNGFile.Text).ToUpper & ",B,P," & mStream.Length & ",0,"
writer.Write(zplToSend)
writer.Flush()
mStream.WriteTo(client.GetStream())
writer.Flush()
End Using
writer.Close()
client.Close()
MsgBox("Send Complete", MsgBoxStyle.OkOnly, "Complete")
Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.OkOnly, "ERROR")
End Try`
You can also open the image file in an IMAGE object and resize it as needed. I had to do this for the label size of the printer.

In VHDL is there a way of limiting the size of a string with a variable value from a process?

My goal is to write a string to a file where the size of the string will vary. At the moment I have made the string very large so that there is no overflow but is there a way to make it so that the size of the string is the exact number of characters I'm placing into it? I've tried something like the code below but it gives me an error unknown identifier "address count" I think it is because address count is a variable declared in a process and address count is constantly changing. Is there any way around this?
signal address_map :string (1 to address_count);
many thanks
leo
"My goal is to write a string to a file." Hence, lets just focus on that.
Step 1: reference the file IO packages (recommended to turn on VHDL-2008):
use std.textio.all ;
-- use ieee.std_logic_textio.all ; -- include if not using VHDL-2008
Step 2: Declare your file
file MyFile : TEXT open WRITE_MODE is "MyFile.txt";
Step 3: Create a buffer:
TestProc : process
variable WriteBuf : line ;
begin
write ... -- see step 4
writeline ... -- see step 5
Step 4: Use write to write into the buffer (in the process TestProc):
write(WriteBuf, string'("State = ") ) ; -- Any VHDL version
write(WriteBuf, StateType'image(State)) ;
swrite(WriteBuf, " at time = " ); -- VHDL-2008 simplification
write(WriteBuf, NOW, RIGHT, 12) ;
Step 5: Write the buffer to the file (in the process TestProc):
writeline(MyFile, WriteBuf) ;
Alternate Steps 3-5: Use built-in VHDL Write with to_string:
Write(MyFile, "State = " & to_string(State) &
", Data = " & to_hstring(Data) &
" at time " & to_string(NOW, 1 ns) ) ;
Alternate Steps 1-5: Use OSVVM (see http://osvvm.org) (requires VHDL-2008):
library osvvm ;
use osvvm.transcriptpkg.all ; -- all printing goes to same file
. . .
TestProc : process
begin
TranscriptOpen("./results/test1.txt") ;
Print("State = " & to_string(State) &
", Data = " & to_hstring(Data) &
" at time " & to_string(NOW, 1 ns) ) ;
One hard but flexible solution is to use dynamic allocation features of VHDL (copied from ADA).
You have to use an access of string (it is roughly like a "pointer to a string" in C)
type line is access string;
you event don't have to do it because line is already declared in std.textio package.
Ok, the problem next is that you can't use an access type for a signal, so you have to use a shared variable:
shared variable address_map: line;
And finally you have to allocate, read and write to this line:
--Example in a function/procedure/process:
--free a previously allocated string:
if address_map /= NULL then
deallocate(address_map);
end if;
--allocate a new string:
address_map:=new string (1 to address_count);
address_map(1 to 3):="xyz";
--we have here:
-- address_map(1)='y'
-- address_map(2 to 3)="yz"
-- address_map.all = "xyz"
Notice the use of new/deallocate (like malloc/free in C or free/delete in C++).
It is not easy to handle this kind of code, I recommend you to read the documentation of VHDL keywords "new", "deallocate" and "access" (easily found with your favorite search engine) or feel free to ask more questions.
You can also use the READ (read the whole line into a string) and WRITE (append a string to the line) functions from std.textio package.

Heading image or string?

I just created a page which the user can choose the mode to show, such as icon (image) or just temperature (text). Those are my code:
<?lc
#tell the browser that we will send binary data (png)
put header("Content-type:image/png")
#get ip address
if $_GET["ip"] = "" then
put $_SERVER["REMOTE_ADDR"] into ipAddress
else
put $_GET["ip"] into ipAddress
end if
#get the mode
put $_GET["mode"] into mode
#get longtitude and latitude data
put url ("http://vo.afteroffice.com/r/v/public/pub/geoloc?ip=" & ipAddress) into geoInfo
split geoInfo by cr and ":"
#input lon and lat data into url
put url ("http://api.yr.no/weatherapi/locationforecast/1.8/?lat=" & geoInfo["latitude"] & ";lon=" & geoInfo["longtitude"]) into weatherDetail
#create tree from XML data
put revCreateXMLTree(weatherDetail, false, true, false) into tLocation
#get data about temperature and clouds
put revXMLAttribute(tLocation,"weatherdata/product/time/location/temperature", "value") into temperature
#create the output
if mode = "temperature" then
put "The temperature is " & temperature
else if mode = "icon" then
put URL("binfile:icon/hot01.png")
else if mode = "" then
put "Oke"
end if
?>
My image & text problems are:
If I don't put put header("Content-type:image/png") in my code and I call mode=icon, the result will be "‰PNG IHDRPPŽò­tEXtSoftwareAdobe ImageReadyqÉe
If I put put header("Content-type:image/png") in my code and I call mode=temperature, the result will be "Te image cannot displayed, cause it contains error"
Could you help me? Thank you.
And how about adding something like
if mode = "temperature" then
# do not put header
else if mode = "icon" then
put header("Content-type:image/png")
end if
at the position where you have your content type header now?
You just have to add the definition of mode at the beginning instead of the middle of your script

Alternatives to macros for accessing data objects

I'm about to begin implementing a new version of an Email marketing program for my company. The old version of the program program heavily depended on micros and has about 2000 lines to prepare data for an email campaign to be run. But I have read somewhere that macros are not the best solution to run such heavy tasks and it's better we keep them for simple things.
I'm quite new to QV and I'm the kind of person that likes to learn as I go and not complete a big reference book before I start a project. I'm good at C# and Java but I realized QlikView scripts are in either VBScript or JScript. I have no experience with them whatsoever but they don't look very complicated to me at first glance.
What I was wondering was whether there is a better way of handling data in QlikView? That means can I use another programming language or do you suggest I stick to the script languages provided by QV? Because one big problem I've seen is that as macros get larger they become very hard to debug.
In the old version of our program developed by one of my colleagues who has now left the company, as soon as there was an error in preparing the data, all we got was the macros window with no clue about where the error had taken place. As I would like to implement this project incrementally and little by little, I would like to have a good mechanism for trouble shooting rather than goring though a 2000-line script to understand where the problem comes from.
Your suggestions about how to bring this project to a safe shore are very welcome. So, any good plugins or 3rd party app to monitor the data and facilitate my implementation can help.
We are an outlier there. We are using the OCX and connect to it in winforms.
We have then standard c# code with everything debuggable and it makes everyone here very happy indead after using endless amount of time debugging javascripts.
The users use QV for selecting stuff and then we use the selected event in the OCX and pull the selected data from QV for postprocessing and tag the QV data with dynamic sql update.
I do not nessesarily recommend this method, but it has increased dramatically the development output for us when using QV for datamining and then processing the data selected.
Next project we are not going to use the OCX. But all the buisness logic and postprocessing is in a com visible c# dll' that we access through vbscript macro.
EDIT. More details
This is the current setup communicating with the document through OCX
Change a selection
axQlikMainApp.ActiveDocument.Fields("%UnitID").Clear();
var selSuccess = axQlikMainApp.ActiveDocument.Fields(cls.QlikView.QvEvalStr.Fields.UnitId).Select("(%UnitID)");
reset a sheet object
axQlikMainApp.ActiveDocument.ClearCache();
axQlikMainApp.ActiveDocument.GetSheetObject("Document\\MySheetObjectName").Restore();
get a string from QV
string res axQlikMainApp.ActiveDocument.Evaluate("=concat(Distinct myField1 &'|' & MyField2,'*')");
and can get horribly complicated
string res axQlikMainApp.ActiveDocument.Evaluate( "=MaxString({1 <%UnitID= {" + sUnitIds + #"}>}'<b>' & UnitName & '</b> \r\n bla bla bla:' & UnitNotesPlanning) & " +
"'\n title1: ' & Count({1 <%UnitID= {" + sUnitIds +#"},%ISODate={'" + qlickViewIsoDate + "'},Need = {'Ja'}" + MinusCalc + ">}Distinct %CivicRegNo) & " +
"'\n Title2: ' & Count({1 <%UnitID= {" + sUnitIds + #"},%ISODate={'" + qlickViewIsoDate + "'} " + recallMinusCalc + ">}DISTINCT RevGUID) & " +
"'\n Title3: ' & Count({1 <%UnitID= {" + sUnitIds + #"},%ISODate={'" + qlickViewIsoDate + "'},Need2 = {'Ja'}>}Distinct %CivicRegNo) & '" +
"\n Title4:' & MinString({1 <%UnitID= {" + sUnitIds + #"},FutureBooking = {1}>} Date(BookingStart) & ' Beh: ' & If(IsNull(ResourceDisplayedName),'_',ResourceDisplayedName)) &'" +
"\n Title5:' & MaxString({1 <%UnitID= {" + sUnitIds + #"},FutureBooking = {0}>} Date(BookingStart) & ' Beh: ' & If(IsNull(ResourceDisplayedName),'_',ResourceDisplayedName)) &''" +
" & MaxString({1 <%UnitID= {" + sUnitIds + #"}>}if(UnitGeo_isRelocatedOnSameGeo=1,'\nOBS! Multiple geo addresses. Zoom!',''))" +
""
);

Resources