Added auto-IP to all Ethernet interfaces. The default auto-IP address for each interface is 169.254.67.85.
Removed IPInfo from the status table. It remains in the settings table, via CRBasic, and the settings editor.
Enhanced FTPClient() by stripping spaces after the , (comma) when multiple files are specified for LocalFileName or RemoteFileName.
Changed FTPClient() to allow a line without a 3 digit leading code through when parsing responses.
Changed FTPClient() so that it starts listening for a data connection before it issues the PORT command. This was done to make sure it is ready to accept when the server tries to open the connection.
Changed FTPClient() so that if commands on multiple files are specified, finish operating on the rest, even if the current one fails.
Fixed FTPClient() by not requiring multiple local files to be specified when attempting to delete multiple remote files.
Changed FTP Client so that it sends "QUIT" command before closing with a failure due to an error response code from the FTP server. This should cause the connection to the server to end sooner.
Fixed FTPClient() when streaming with the option to either put in the header or not based on if the file is present on the server. After storing successfully without a header, i.e., detecting the file is present, if the file is deleted on the server we did not redetect properly that it was no longer there.
Changed the FTP Server so that the LIST and NLST commands can have paths prefixed.
Enhanced FTPClient() so that when streaming a data file, if the FileOption is negative, the header is added only if the file currently does not exist on the remote server. An example of a common example is FTPClient(host,user,pass,"TableName","data.dat",9,0,60,Min,-1008). Note that in this example, the PutGetOption is append and FileOption is both +1000 and negated.
Added the maximum number of concurrent FTP Server connections and limited it to 8.
Fixed HTTPGet() when the response transfer encoding is "chunked". Symptoms were HTTPGet() not completing / timing out after 75 seconds and chunk values not being parsed but instead showing up in the result.
Updated http by setting a timeout if a stray http packet is received to help prevent using datalogger bandwidth. This was done so we don't waste bandwidth trying to poll for the rest of the packet continually.
Changed HTTPGet() so that if there is an error and the response is directed to file, it then writes the error message to the header parameter if it is a variable.
Added a new IP trace code of 0x800 (2048) for http.
Fixed the HTTP web server for file names and unknown file types.
Modified HTTPGet(), HTTPPut(), and HTTPPost() so that they can be used against a HTTPS:// URI even when the URI is a variable. TLS will be enabled and memory allocated for each Sequence when it contains a HTTPGet/Put/Post command and a URI that is a variable or when the URI is a constant specifying a HTTPS:// address.
Added Content-Disposition to the web server.
Removed possible window (very small) where JSON files would return "more-true" when there is no more. (significant)
Fixed web server when displaying string variables with a '%' embedded.
Changed web server so that the number of records displayed is not limited to the size of the CPU table size when a card is in use.
Changed HTTPGet() so that if the destination is a file, it will not be opened until after the connection to the server is made. This prevents a file serial number, controlled by the Files Manger, from incrementing when the connection cannot be made, avoiding gaps in the serial numbering and hence fewer files kept than specified by the Files Manager Setting.
Fixed NTP when the domain is not cached and needs to be obtained via DNS server. A 0 offset was
Changed PakBus hop metric for TCP connections to be 1 sec instead of 5 sec unless the connection is over PPP.
Changed PakBus/TCP to not close the TCP connection if a route is lost but neighbors still exists on the connection.
Fixed PakBus/TCP Password authorization so that the TCPOpen() does not return a connection before the authorization is complete. This manifested as not being able to connect with Konect GDS.
Fixed dialing a modem via PPP or Modem Callback so that if dialing fails, and the modem outputs unknown characters to the datalogger, that the echo process continues to work.
Fixed PPPClose() to get rid of the 5 second delay and to not inadvertently close the NL240 also.
Fixed possible asynchronous problem when dialing a modem with PPP.
Removed looking for "CLIENT" while connected in PPP.
Modified PPP so that if a comport is setup for PPP, don't let any characters enter the Terminal Mode even if the program has closed PPP.
Changed PPP so that when closing the session is unsuccessful, send +++ and AT+CGATT=0 to try to get the modem off line.
Enhanced PPP dialing messages in IP trace and IP status.
Fixed PPP so that a static IP address can be used.
Modified SNMP string variable to make sure we cannot overwrite size of 255 characters max.
Fixed SNMP ESS stations for setting strings and for a blank community name.
Added SNMPVariable() to map variables into an SNMP OID.
Changed TCPOpen() to allow listening on a port for multiple concurrent connections.
Enhanced TCPOpen() so that when it is listening on a port (IP address is null), it will handle multiple concurrent connections up to MaxConnect connections. When used this way, TCPOpen() is not to be called in a loop for each connection as is done when the multiple connections are as a TCP client. Rather, for each connection that is accepted, a vacant slot in the array is found and filled in with the connection handle. This allows multiple connections to be handled by the service protocol defined by serial I/O instructions. TCPOpen("",3000,1000,7500,Handles,MaxConnections) 'listen for multiple connections on port 3000. For I = 1 to MaxConnections : If Handles(I) > 100 Then : IPAddress(I) = IPInfo(Handles(I),1) : Else : IPAddress(I) = "" : EndIf : Next I
Changed TLS memory allocation to accommodate more than 1 HTTPS connection concurrent within the same sequence since these connections can stay open after the instruction exits.
Increased the stack size for TLS needed for TLS client connections.
Changed TLS memory allocation to wait for up to 3 minutes if memory is not available instead of watchdogging. This will help when running TLS concurrently in different CRBasic sequences.
Modified UDPDatagram() so that when the IP address is blank, it will listen for and queue up incoming datagrams. Also UDPDataGram() will return a connection handle when a datagram is queued, put the received data into the UDPRecVar variable, and indicate the message length of the received data in the UDPSendLen variable.
Fixed keyboard display security challenge to not incorrectly re-challenge when backing out of a secured menu.
Changed indentation (reduced) of displayed values while editing constant in ConstTable.
Added in keyboard display ConstTable editor an "Apply and Restart" flag that will cause the changes to the ConstTable to be applied and the program restarted. This behaves the same way as when you escape from the ConstTable menu and are prompted to save the changes.
Updated keyboard display of settings to show all logger settings available. Previously only a subset of settings were displayed for editing.
Changed keyboard display of settings. Settings are split into "general" and "com ports".
Fixed keyboard display directory of a card with > 2 Gig memory.
Changed the Communication Allocation setting to also adjust the big packet size (the second field in the first line in CommsMemFree). This is needed so the logger can stream in large generic data packets for serial I/O.
Changed FTP and HTTP putting files onto the datalogger to do it from the IPServer task so that if was it was taking too much time in the IP task, it would cause it to not watchdog.
Fixed writing an IP trace file in cases where the disk/drive was full.
Modified IP static and dynamic routes to give precedence to static routes.
Changed TCP/IP Info so that the default network is listed. The default network is listed as “XXXXX is Default Network” where XXXXX could be CSIO(1), CSIO(2), ppp, or eth. Instructions that need access to a specific TCP/IP address (or DNS name) that has not been listed in the IPRoute() instruction will use the default network to try to do its work. Those listed in the IPRoute() instruction will use the specified Ethernet interface to do its work.
Modified it so that IP Info displays ipv6 default routers.
Changed 'W' sniffing of IP trace so that it restores the original trace code when it exists.
Fixed SetSetting("PakBusTCPClients","18.104.22.168:6785") to allow a : (colon) before port. The officially recommended syntax is SetSetting("PakBusTCPClients","(host1,port1)(host2,port2)(host3,port3)(host4,port4)"), however in reality the host and ports need only a) to be specified as one single string and b) be separated by a delimiter like space, comma, colon, semi-colon, etc.
Shortened the advertised wait time for TCP when doing os_recompile.
Fixed data streaming triggered by the offset into interval parameters when the units were something other than seconds.
Fixed data table streaming of a single element within an array.
Enhanced IPNetPower() so that when turning power off to an IP network, if no other network is active, all the IP connections will be closed.
Changed IP tracing we don't run into a possible, rare, memory leak of CommsMemFree when concurrent tasks are IP tracing.
Modified TCP/IP Info so that if no IP networks are present, it will display "No IP Networks".
Fixed some communication instructions including AVW200's when the route is via TCP/IP but with a static route.
Added string length attribute to JSON and XML queries.
Fixed JSON formatted files (missing head) generated by TableFile and by streaming via FTP, email, and http. (significant)
Changed initialization of data streaming based on interval in the case there are records already stored on the first execution.
Added a 6th parameter (optional) to DNP instruction; 1 means TLS enabled.
Fixed DNP3 when the swath for the DNPVariable instruction is 1.
Fixed SDM-SIO1 DNP3 Master.
Changed the DNPFlag parameter so that if the flag parameter is smaller than the array for the source parameter, then the last element of the flag array is used for all of the remaining source array elements.
Changed the DNPEvent parameter so that if the DNPEvent array is smaller than the source array, the last element of the DNPEvent array is used for all of the remaining source array elements.
Changed DNP3 so that more than 65535 events can be stored and so that it does not use twice as much memory as needed.
Added DNP3 indexing into arrays so that multiple DNP3 classes can be specified with one source array.
Changed DNP datagram implementation so that if DNP comport parameter is negative then PakBus Datagram is activated.
Added an optional parameter to DNPUpdate() called ConnectHandle that provides a TCP Connection Handle controlled by TCPOpen().
Added support for DNP3 Unsolicited Responses.
Added support in DNP3 for single precision floating point.
Added DNP3 support for object 50, variation 1 (read time and date).
Changed the meaning of the link verification, timeout parameter in DNP() as follows: 1000 = Disable link layer confirmation, disable link verification, application layer timeout is 60 seconds. 1sss = Disable link layer confirmation, disable link verification, application layer timeout is sss seconds (max is 60 seconds). 0000 = Disable link layer confirmation, enable link verification, application layer timeout is 60 seconds. 0sss = Enable link verification, link layer and application layer confirmation timeout is sss seconds (max is 60 seconds).
Fixed erroneous closing of comport that is open for PPP or serial comms when characters directed to the terminal are intercepted.
Fixed GetVariables() responding to command when the remote wants ASCII and our variable is NSEC (timestamp), return the date/time instead of NAN.
Fixed GetVariables() when the destination variable is an array of type string and is referenced with a variable index into the array.
Fixed GetVariables() when the destination variable is of type string but the value in the remote is of some other type.
Changed PakBus routing so that if a static route is specified by the neighbor address and there is also a route to the destination with the same neighbor address as specified statically, then use the comport to the neighbor in the list instead of the statically declared comport.
Changed PakBus set value so that it can set an FP2 value when the source is not FP2.
Fixed the Routes() instruction for a non-router in the case that there are "potential neighbors", as in the case when there are allowed neighbors that have not been verified.
Modified SerialOpen() so that if a delay is specified before transmit on the comport, then wait an extra 3 * the delay time when sending ring packets out before the main packet.
Increased terminal stack size by 1K.
Fixed Network() for a fixed begin address.
Fixed displaying SDI-38 in status instead of SDI-12 when using CWB100.
Changed terminal mode so that characters cannot enter terminal from a comport that is being used by the program via SerialOpen().
Modified fwrite_bytes so that if MBX is full and does not succeed, releases memory.
Fixed SendData (PakBus one way data send) when sending the Public table.
Changed behavior when the Beacon Interval or Verify Interval is changed so that PakBus neighbors are verified instead of a broadcast hello request message sent out the comport.
Files Manager setting for 3209 ("sniff") and 3212 ("IP trace") changed so that (1) a drive can be formatted if the setting is actively writing to the drive, (2) if writing to a CRD, pushing the card button will temporarily halt writing to the file, and (3) deleting the setting will allow the file to be deleted.
Modified SerialOut() so that when waiting for echo, or for a string, will flush the buffer before each output.
Changed SDE Enable Comport to 31 instead of 16 and allow the compiler to pass this comport into SerialOpen without error.
Fixed initializing card pointers after a power cycle. Problem occurs if there is a power cycle and a table using DataInterval is writing to the card and has written a sector to the disk but has not gone far enough to write a full TOB3 frame and update the card record number. When power is restored, the file pointers are not correctly aligned after resuming operation. This results in a file that cannot be converted without the repair option. The fix is to move the read pointer back to the start of the CPU buffer so the first sector is written again.
Changed the behavior on program start when using existing files on a card. If a power cycle occurred during card initialization, it often resulted in a yellow light and data not being written to the card. The behavior was changed so that if at program startup, initialization of an existing data file fails. The associated files are deleted and new files are created. The thinking here is that the files were deemed to be corrupt anyway, so removing them and starting fresh seems better than leaving the logger not writing to the files. (significant)
Fixed SendVariables() and GetVariables() when the timeout expires at the same time the response is received in the case where the response code and/or source or destination parameters are variably indexed.
Modified SerialOpen() if it specifies PakBus Active and TXDelay and fragment size, then delay 4 * TXDelay extra before retrying hello message.
Changed Files Manager setting for 3209 ("sniff") and 3212 ("IP trace") so that (1) a drive can be formatted if the setting is actively writing to the drive, (2) if writing to a CRD, pushing the card button will temporarily halt writing to the file, and (3) deleting the setting will allow the file to be deleted.
Removed adding 8192 bytes to the size specified when setting the USR drive size.
Modified starting a slow scan to wake up slow measurement task immediately.
Added SC115 change file attributes.
Changed shutting down a comport when it is used as a control port instead.
Changed setting user (USR) drive size so that it maxes at 2990000 bytes.
Added warning message if the CPU: drive cannot be opened; give warning message and format the drive.
Changed SerialInChk for SDM-SIO1 to return 13 bits of receive data. It is no longer meant to return the most significant bit.
Corrected a problem using the Const declaration when using values exceeding (2^31) – 1 (2,147,483,647). If a value greater than (2^31) -1 was used as the constant, the actual value used in the program was 2,147,483,647. If a user's program contains a Const declaration with a desired floating point value greater than 2,147,483,647, they can correct previously gather data by doing a simple calculation. To correct calculation errors caused by this issue a user will need to reprocess values obtained using the erroneous constant. For example if the Const in question was used as a multiplier, you should divide the result by 2,147,483,647, then multiply by the actual desired constant.
Changed compiler to allow a reference to tablename.fieldname() to act the same as tablename.fieldname.
Fixed compiling a program that is missing a referenced sub routine. This was crashing the PC compiler since FunctionsPtr is NULL yet was used.
Changed compile time error checking so that we don't flag a compile out of bounds error for covariance if a variable index is issued for the source. At run time an out of bounds will be flagged if necessary.
Modified SpaAvg() so a compile error will be reported if the swath parameter is a constant that is beyond the boundary of the source array.
Add -u command line in PC compiler. This option will instruct the PC compiler to check for and report unused variables and subroutines. For example "cr1comp.exe -u myprog.cr1" would report "Warning: VarA declared but not used" if myprog.cr1 had a variable VarA declared, but VarA is not actually used within the program.
Enhanced Instr() function by adding Search Options 9 and 10. Search options 9 and 10 find the start of FilterString, starting at the end of the string and searching backwards through SearchString until it finds the beginning of FilterString, reaches the StartString position, or reaches the beginning of SearchString. Option 9 performs a case sensitive search. Option 10 performs a case insensitive search.
Modified the pre-compiler code so it no longer allows Subroutines to be declared inside If..EndIf. Catch unterminated If in EndSub.
Added OSVersion to predefined constant list. This predefined constant can be used to determine the datalogger operating system version at compile time, which can be particularly helpful for conditional compilation of programs using #IF/#ELSEIF/#ENDIF.
Changed SetStatus() changed so that the settings list is checked first to determine if the field to be set is in both the status table and in the settings (like "StationName"). If so, the setting will be changed along with the status table. This change was introduced due to the restructuring of the Status table and settings and with the introduction of the SetSetting() instruction.
Added new datalogger settings, EthernetEnable, CSIO1netEnable, CSIO2netEnable. Setting to FALSE will turn off / disable the associated interface unless the setting is changed to TRUE or unless IPNetPower() or EthernetPower() are used to turn it on under program control. The new settings specify the power state of the interface at boot up.
Added new datalogger setting, DeleteCardFilesOnMisMatch. This setting controls the behavior of the datalogger when it restarts with a different program and it detects that data files created by the CardOut() are present but do not match the new program. If this value is set to one, the datalogger will delete these files so that new files can be stored. If set to a value of zero, the datalogger will retain the existing files and prevent any data from being appended to these files. The default is 0 so that the default behavior is the same as it has been prior to the addition of this setting.
Removed compile warning message in the case that an infinite scan/nextscan is inside a conditional statement.
Enchanced IfTime(), TimeIntoInterval(), and DataInterval() by adding interval Units option of Mon (Month). MON is the predefined constant for MONTH and has a value of 6. This option behaves differently than the other parameters. If the UNITS parameter is MON, the INTERVAL parameter is specified in months, and TINTOINT parameter is specified in seconds into the current month. The INTERVAL is synchronized to the beginning of the year, January 1st. If the current month of the year modulo the INTERVAL equals 1 and the seconds into the current month matches the TINTOINT, then the condition is true. If TINTOINT is negative, then the TRUE condition will be in the previous month. Examples, IfTime(0,1,Mon) 'true at midnight on the first day of every month : IfTime(1209600,1,Mon) 'true at midnight on the fifteenth day of every month : IfTime(-43200,1,Mon) 'true at noon on the last day of every month : IfTime(0,3,Mon) 'true at midnight on the first day of January, April, July, and October
Modified the compiler to flag an error if the iterative variable in For/Next is not a variable.
Fixed PWM() when using multiple PWM() instructions on same port. Previously doing this caused caused the duty cycle of the non-first PWM's to be zero due to an uninitialized pointer. The work around for previous OS version is to use one PWM per port and make the duty cycle a variable.
ETsz() changed to force units and fieldnames.
Array manipulation fixed when the dimensionality is 2 or 3.
Added default units of mm and MJ/m^2 for ETsz().
Fixed compile error for PC compiler due to an out of place declaration.
Fixed setting of an array element contained in an array that is only partially aliased. The problem only occurs when the array is split into more than one part (through discontinuities in the alias process) and you are accessing a part that is above the alias. When I found in the table the array name (the first part, below the alias) but found that the element requested was not in that first part, I aborted looking beyond and flagged the error. The fix is to instead keep looking through the table.
Fixed NewFile() to work with a Boolean result. If the type is Boolean, rather than incrementing if the file is not there, it is set to -1.
Modified subroutines to pass back strings and make sure the last character is 0.
Fixed maximum error check to make sure the error message is not too large. The bug would cause an out of bounds memory crash on the PC compiler for errors in a long line.
Changed SolarPosition() to use UTC_OFFSET setting if it is not -1 (inactive).
Fixed sprintf(dest,"%b",val) when val is negative.
Modified Files Manager setting 3209 so sniffing will start up when card is inserted. Also when the card is removed or the drive formatted, it will close the file it was writing to.
Fixed FieldNames() so it will flag an error if the parameter is a variable.
Fixed alias strings when the variable they are aliasing has a string length of 1 (single character aliases).
Fixed Public declaration of d (or D) followed by 3 or more spaces or tabs. This was causing compile issues.
Added OS version to the watchdog file.
Modified the compiler so units name of " (empty string) is flagged as illegal.
Changed FieldNames() so that it accepts a constant string.
Added an optional parameter to Sample() which will define the field in the most recent record as READ_WRITE if the parameter is 1.
Modified the precompiler so it no longer allows subscan to call a subroutine with measurements.
Enhanced it so that we now initialize exe_time_us so PC CRBasic compiler does not crash.
Changed CDM instructions to allow certain parameters to be searched from module specific predefined constants rather than the global datalogger defined constants.
Added Encryption AES128 support in CRBasic.
Enhanced the OS so we now allow ! (at pointer) operation on user function calls.
Added new instruction TimeIsBetween(Begin,End,Interval,Units). This instruction will return true if the datalogger's time is between Begin and End, otherwise it will return false. If used within a Scan() the scan time will be used, otherwise it will use real time; this is the same behavior as the RealTime() instruction. A common application of this instruction is to turn a communications peripheral on between 9:00 and 17:00 and off during all other times, TimeIsBetween(9,17,24,Hr).
Added a specific error message on SetSettings() and SetStatus() if they cannot find the wanted field.
Fixed array assignment so that this case C(1)() = A() is now possible.
Added ! and @ operators that provides pointers to variables.
Fixed formatting CRD: for very large (>2G) cards.
Fixed the PC CRBasic precompiler. A variable declared inside of code does not compile in the Microsoft environment.
Fixed to now allow the table name in GetRecord() to be a variable.
Modified it so that if the table name is a constant, then allow Tablename.Fieldname and GetRecord(tablename) to work with the constant declaration, as in : Public MyInfo As String, MyRecord As String * 50 : Const T = "Table" : Public Name As String : DataTable(T,TRUE,-1) : Sample (1,Name,String) : Sample (1,"Hi",String) : EndTable : BeginProg : Name = "Hello" : Scan(1,sec,0,0) : CallTable(T) : MyInfo = T.Name : GetRecord(MyRecord,T,1) : NextScan : EndProg
SDI-12 recorder changed so that if 0 is returned for the number of values in response to the M or C command, NAN is put into the first element of the array and the instruction returns.
Modified the OS so that the CPU: is now FAT32 formatted. This eliminates the error of insufficient space for file names. (significant)
Fixed compiler a crash for this and other possible illegal syntaxes: Public = name.
The default string size is now 23. (significant)
Changed the string declaration minimum size from 23 to 3.
Changed the error message when declaring units to a variable that are not declared Public nor referenced as a source in a Data Table.
Fixed FP2 to string conversion that were causing errors in conversions.
Modified Table.Field(x) to now ignore x if only 1 single dimensioned field name "Field".
Fixed calling a table from a scan with an interval greater than 1 hour when the table does not use DataInterval().
Fixed For .. Next name(i) to not flag an error ("Too many parameters").
Fixed Windvector() standard deviation calculation when disabled at output time.
Added new IPAddress() CRBasic instruction.
Added a reset optional parameter to AvgRun().
Added TotalRun() instruction. The TotalRun() instruction The TotalRun instruction is used to output a running total of a measurement.
Modified the compilers so they will work with optional parameters in a user function. Commas are not required when calling the function without the optional parameters.
ArrayLength(Field) changed to allow the Field parameter to be TableName.FieldName.
Added command line switch -s for signature to the PC CRBasic precompiler.
Modified SetStatus() and SetSettings() so they will execute at compile time if the value is not variable and if the setting is changed and requires a reset. The reset will not happen until the compile process is complete, which avoids possible multiple resets if multiple settings are changed.
Fixed frequency bounds checking for CDM-VW300.
Improved VibratingWire swept frequency when using the auto-step size.
Modified the compiler so it no longer allows PulseCount() within a SubScan.
Fixed the Case expression so that conversion of the expression or the test expression from string to numeric, if necessary, is performed before the equality test is performed.
Changed Select() to not require Case before the test expression. Select expression is legal and is the same as Select Case Expression.
Fixed the "Case NAN" statement to work correctly when the test expression is a NAN.
Fixed the precompiler when there is a CASE IS statement and the required comparison operator is missing. It now flags an error.
Modified the OS so we can store Settings.name via the Sample() instruction in a data table.
Fixed passing subroutine parameters in and out and when doing a conversion from float to string is necessary. The string was formatted as "%7g" instead of "%.7g".
Enhanced the OS so that when passing a parameter of type string, we copy the size allocated for the destination variable instead of the size of the incoming string. This will allow null characters to be passed in.
Fixed format printing FormatFloat() and sprintf() when using %.ng (and G) where n is the precision (the number of significant digits) needed.
Allow the syntax ArrayName(Index)() to be used with the Disable Processing parameter to rep through an array starting with Index.
Modified SolarPosition() by removing limiting the zenith angle to 9 degrees.
Changed SolarPosition() Azimuth calculation to match SolPos.c rather than the Fortran and CRBASIC adaptations received from RSR2. This was done to help make SolarPosition() more accurate.
Added the EncryptExempt() instruction. The EncryptExempt instruction is used to define one or more PakBus addresses to which the datalogger will not send encrypted PakBus messages, even though PakBus encryption is enabled.
Fixed XMLParse() so that if the result code is an error or it is at the end of the file, then close the file and release any memory used by the large string. Also, eliminated the need to "Initialize" and added "Finished" in the element name space to specify done with parsing.
Fixed XMLParse() where, in some cases, it did not parse correctly when white space followed an = character.
Added two optional parameters to ConstTable so that it now has the optional syntax of ConstTable(TableName,Hidden). TableName is specified as a unquoted literal. The Hidden parameter specifies if the table should be hidden always when security is not used or only shown when security level 1 is entered, i.e. the same behavior TableHide() creates for DataTable. Specifying TableName, causes the datalogger to map the constants in the ConstTable to a one record datatable (like Public, Status, and DataTableInfo). The table will automatically include an "ApplyAndRestart" field that when set true (non-zero), will cause the current values of datatable fields to map back into the constants in the ConstTable and then restart/recompile the program. This process updates/changes the text of the CRBasic program residing in memory. This new feature allows the ConstTable to be easily updated from software just like the Public table can be.
Added the ability to change constants in ConstTable(TableName)/EndConstTable under program control using the syntax of SetSetting("TableName.ConstantName",Value), including the auto-created ApplyAndRestart field. This only applies when the ConstTable has been assigned a table name.
Added a new program structure called ApplyAndRestartSequence/EndApplyAndRestartSequence. This instructions inside this sequence are executed when the ApplyAndRestart field of the ConstTable(TableName) is remotely set true, i.e. set from outside the program - most likely from KD or software, but before the values are mapped back and the program recompiles. The intention is that a user can validate the values of the ConstTable before they are applied. Example usage is : ConstTable(Settings) : Const A = 1 : Const B = "Hello" : EndConstTable : ApplyAndRestartSequence : 'if trying to apply an out of bounds value for A, set it back to the current value : If Settings.A < 1 OR Settings.A > 10 Then SetSetting("Settings.A",A) : 'if trying to apply an empty value, set to "ERROR" : If Settings.B = "" Then SetSetting("Settings.B","ERROR") : 'REQUIRED AFTER VALIDATION IS COMPLETED : SetSetting("Settings.ApplyAndRestart",TRUE) : EndApplyAndRestartSequence
Fixed Function references with op eq (+=, -=, &=, etc.) when operating on a function return variable.
Added a flag to account for a compile error when doing FunctionName +=, &=, etc., operations.
Modified the Move() instruction's source parameter expression so it can be more than a simple expression and allow an auto indexed variable, as in SrcVar1() * 2 + SrcVar2().
Added %I in snprintf() to allow printing IPV4 addresses from a LONG input.
Fixed ABS(X) which was broken in OS26 when the expression X is of type float and ABS() is inside an expression with arguments with a type of LONG preceding ABS(), as in 100 * ABS(X).
Quadrature() changed to allow multiple data types in result.
Fixed AVW200() to allow .01 as a valid threshold. This problem was caused by a double precision comparison of a float value. The MIN_THRESH_HOLD was defined as .01. The compiler used doubles to represent this value. The user input was .01 as a float which is not exact. The fix was to force the defined threshold to be a float.
Added options to InStr() to search from end of string.
Fixed a memory failure issue with Windvector().
Modified OS to allow ApplyAndStart() to be true if non-zero.
Fixed pointer operations and added a . qualifier to the ! operation to ensure pointers to floats do not truncate the fractional part when used in an expression where the following operand is long.
Changed GoesSetup() to that the minimum interval can be set to 5 minutes rather than 10.
Changed SDI12Sensor() so that if the response time specified is 0, then 1 second is used in the response. In reality the logger is not ready to receive data instantaneous.
Modified the OS so when resetting the settings coming from OS download. For the control port /comports, set the flag that says the baud rate was set via the settings instead of from serial open.
Changed warning message from "Default Settings were removed" to "Default Settings might have been removed" since when coming from downloading an OS via LoggerNet or FileControl, if the settings are different, the default settings are restored but then all the settings that were the same in the old OS are then restored, meaning that only new settings are set to default.
Removed OS version from check to using data on a card.
Fixed loading a .gz zipped OS file.
Added a 40 second timeout loading OS via file tab, after which it will commit the OS if not Set maximum number of tables that have Tablefile() to 30. (significant)
Modified the OS for streaming data so that the optional parameter 'interval' cannot be non-zero when the table specified is Public, Status, ConstTable, or DataTableInfo. Also, when streaming Public, Status, Constant, or Datatableinfo, increment the record number so there is a record to send.
Fixed the compiler to flag an error if more than 1 DataEvent is declared inside a Data Table.
Fixed compile error for reps=0 in final storage instructions.
CPUBytesFree, USRBytesFree, and CardMemFree moved out of the Status table but can still be accessed via CRBasic, or PakBus, or the K/D under Settings.
Allow CPI fields to be cleared.
Moved the Data Table information from Status to DataTableInfo. (significant)
Changed Status.CommsMemFree to a string variable. (significant)
Enhanced expressions so that an entire array can be assigned to an expression.
Fixed getting tablename.fieldname(N) where N > 1 and the field's beginning index is > 1.
Allow > 30 data tables. (significant)
Removed several items from the Status Table that are settings. All settings can be set with SetSettings() and with the keyboard display. SetStatus() is identical to SetSettings(). Access to all settings is through the syntax of Settings.name or through Status.name.
Enhanced the OS so it now reads port status and SW12 when getting the Status table.
Fixed SDM-SIO1 ModbusMaster() problem with back to back requests if the timeout happened a little before data comes in from a preceding request.
Fixed ModBusMaster() to properly respond with -11, -16, and -20 for internal errors.
Enhanced ModbusSlave() so that ReadOnly instruction also applies to Modbus registers and coils; previously it only applied to PakBus communication. If a master/client attempts to write to a register or coil that has been marked as ReadOnly, the datalogger (slave/host) will set the most significant bit in the function code when responding, indicating an error, and the actual error code to a value of 0x01. It is very common for the datalogger acting as a Modbus slave/host to only need to serve up data values and not allow them to be changed. Example, Public Reg(5), Coil(2) as Boolean : ReadOnly Reg, Coil : BeginProg : ModbusSlave(502,0,1,Reg,Coil,2) : EndProg
Fixed ModBusMaster() over TCP when more than 1 response is in a single IP packet.
Enhanced ModBusMaster() instruction to optionally not wait until the response is returned.
Enhanced the Modbus option so that at run time the Modbus option can switch back and forth from ASCII to not ASCII.
Fixed ModBus ASCII Slave over a SDC comport and also if there are more characters input beyond the line feed terminator of the packet.
Fixed ModBus ASCII over a serial comport if there are delays in the packet returned.
Changed ModBus Master over TCP so that an incrementing transaction number is sent and multiple Modbus Masters can run concurrently in difference sequences.
Added ModBus Slave to be a TCP Client using the connection comport handle returned by TCPOpen().
Added ModBus start register offset to be greater than 10000.
Fixed ModBusSlave() when multiple instructions over TCP/IP are used in order to map different Modbus registers of different types to datalogger variables. Before, this worked only if all of the instructions specified a non-zero offset.
Added a 16 bit unsigned integer data type to ModBusMaster() and ModbusSlave().
Fixed Modem Dial to delay long enough for PakBusMain to start dialing before it monitors when dialing is complete to flag whether or not it was successful.