Skip to content
September 6, 2022 / shipwrecksoftware

Simple Wi-Fi Analyzer

New app in the Microsoft app store! The Simple Wi-Fi Analyzer will scan for nearby Wi-Fi hotspots and present you will lots of information about each one!

The app will automatically scan for all available Wi-Fi hotspot (in the example, I did a scan at a mall).

You might need to see how many hotspots are on the different Wi-Fi frequencies (channels) and bands. The “chart” option shows you exactly which hotspots are where, and how strong they are. In the example image, in the 2.4 GHz band the Wi-Fi hotspots are mostly set up correctly on channels 1, 6 and 11 where they don’t overlap. You can see that those channels have full-height bars in them. The other (like channel 2) is full from the “spill-over” from channels 1 and 6.

You can also get a full table showing all of the access points. You can sort by any of the columns and filter by any value. You can also copy the data to the clipboard either for Excel or in CSV format.

December 22, 2021 / shipwrecksoftware

Best Calculator updated!

BASIC for Best Calculator keeps on getting better and better, with new features to make programming easier. Check out the latest news at https://bestcalculator.wordpress.com/best-calculator-news/.

August 15, 2021 / shipwrecksoftware

New app! Communications for Compumate

The Compumate (otherwise known as the Laser pc3 from Vtech) is a late-1980’s notebook style personal computer. It’s bigger than a PDA, but has the same kinds of functionality. There are a set of built-in apps, and data is stored in “static RAM” for as long as the batteries last.

vtech compumate laser pc3 notebook computer 1989

The Communications for Compumate app in the Microsoft Store lets you download data from the different built-in apps. It can read in data from the telephone directory, the personal files, the appointments, and the word processor.

This is very much a version-1 program. The end result is that the data is displayed to you in the app; you have to save it into files or convert the telephone directory entries into real contacts yourself. And it doesn’t support modifying the data, or uploading data. It also doesn’t support the BASIC program (the BASIC language came on a separate cartridge which I don’t have) or the Expense Report data (which is more complicated).

Note that you have to use a USB-to-serial port adapter. Because it’s a UWP program, I don’t have access to built-in serial port. Or maybe I do, the documentation wasn’t very clear, and I don’t have a machine with built-in serial ports. Because it’s past 2020, for goodness sakes, and USB has been a “thing” for 20 years. You’ll also need a nine-pin to 25-pin adapter, and an RS232 mini-tester is always handy.

You will need to set the serial port parameters in the Compumate. My app is hard-wired to supporting 9600 baud, even parity, 1 stop bit.

More images!

Review of the vtech compumate laser pc3:

I want to like this little notebook! When all of these small computers came out — and there was a whole flock of them, including the Tandy 100, the Cambridge Computer Z88, the Atari Portfolio and the HP75 — I couldn’t justify them. Now that I have this particular one, I can confidently say:

  1. The screen is too small. The programmers made a great effort to make a useful device with this kind of small screen, but it’s just not big enough
  2. The keyboard is the single worst keyboards I’ve ever used. If you type too fast (and too fast isn’t very fast), the keypresses get duplicated. You have to press down exactly square: a sideways press feels like it “squeaks”. And the organization is weird.
  3. The apps are mediocre. The calculator could have been awesome, but instead it’s just a four-function calculator
  4. The choice of having a single oddball combination serial port/parallel port was unfortunate
  5. For goodness sake, why isn’t there a serial terminal? It can dial a phone, but it’s can’t do telnet!

In short, it’s 100% not a top-grade device. To be fair, it was priced accordingly.

January 31, 2020 / shipwrecksoftware

What the heck is require(“Smartibot”)?

The next update to my Bluetooth Device Controller program will have more Robot controls! The last one to get more support is the awesome Smartibot — it’s an Espruino-based robot, meaning that you program it in JavaScript.

There were two big hurdles for controlling the SmartiBot. Firstly, it’s a blend of a Bluetooth LE device, meaning that it uses services and characteristics, with the conceptual background of a classic COM-based device. That means I need a “terminal” to write to it, but the terminal has to poke at specific characteristics to send and receive data. That part was a little painful, but straightforward; I’ve done that kind of programming before.

At this exact moment in time, it’s still painful: the write dialog box so send data pops up right on top of the output area, so there’s a lot of clicking open a write dialog, paste in commands, close the write dialog so I can see the read area, and back again. That will be cleaned up in the final version.

The more painful part is that only a tiny number of Smartibot programs actually wanted to work. That’s because the Espruino-based system uses the Node require(“Smartibot”); to load Smartibot-specific things. The actual Smartibot hardware, when you send that down, just replies with

require("Smartibot"); 
Uncaught Error: Module Smartibot not found at line 1 col 20
require("Smartibot");
                   ^

Most blog post that talk about the require statement are all about the deep, deep technical details of loading modules. Finally, there was a clear explanation: require just does a https:// get. The require(“Smartibot”); statement just pulls down a JavaScript file from https://www.espruino.com/modules/Smartibot.js. There’s actually a bit more: an “exports” object is made, and then that object get returned.

Woot, woot! that file is the magic key! It’s not quite right — by itself, my system can’t quite read it in. But what I CAN do it munge the file around a bit, and shazam! the eyes light up!

All those =undefined results..

Wondering why so many JavaScript commands spit out “=undefined >”? Tearing your hair out about why you are getting this error? Turns out that it’s just JavaScript’s way of saying that you called a function that didn’t return anything. Instead of something friendly like, “Function called OK”, it spits out the remarkably unhelpful =undefined.

Time wasted debugging something that’s not a bug at all: 2 hours.

Other robots coming up!

The next release will support four robots: the BERO, the Smartibot, the Slant robot LittleBot, and the amazingly small and cute Skoobot!

January 5, 2020 / shipwrecksoftware

Don’t reinvent the wheel! Use the Standard Robot Car protocol instead

 

SRC: Standard Robot Car serial protocol

Are you one of the many people designing a little Bluetooth car using an Arduino? And is your Bluetooth connection through one of the popular HC 06 or HC 05 Bluetooth serial-port chips?

After extensive research on GitHub, here’s the most common protocol to control cars. This is directly supported in

             F forward 
L left       S stop       R right
             B backward

G left forward      I right forward
H left backward     J right backward

W lights ON      w lights OFF
U rear lights ON u rear lights OFF
V horn ON        v horn OFF

Q Device Query (report back your car name)
P Ping (report back the status of the distance sensors)

Your code should ignore unknown characters and should definitely ignore characters like CR and LF (\n and \r).

This scheme is used by these popular devices

I have also added support for this scheme to my own Bluetooth Device Controller program for Windows; just scan for Bluetooth COMM devices, and when you see your device, ask for the Standard Robot Car control set! (support is added to the latest versio which is estimated to be in the store later this week)

December 26, 2019 / shipwrecksoftware

More Bluetooth! (Update: and Slant Robotics, too!)

Coming up: additional devices will be supported in the Bluetooth Device Controller app.

First up will be the latest TI SensorTag model 1352. This new SensorTag support was a struggle; the characteristics are once again mostly undocumented. After a time, I realized that many (but not all) of the values are now published as floats instead of the more complex values they used to serve up.med_lpstk-cc1352r_lpstk_cc1352r_extra-1

Also part of the release: support for the Mipow Playbulb, model BTL-201. Any number of snarky comments can be made about the random mess of characteristics that the bulb has (like, for example, it still claims to be a heart monitor and not a bulb at all!), but the bulb itself works like a charm.

Mipow_Playbulb_BTL201-175

And for the first time, source code for the application is available on GitHub!

The Bluetooth Device Controller app version 1.3 is currently (2019-12-28) going through the store review process.

Better news! I’ve got a nifty update to the Bluetooth Device Controller program for Bluetooth serial devices. Directly supports devices will include the Slant Robotics LittleBot (!)

October 13, 2019 / shipwrecksoftware

Modern IOT number formats

A flood of IOT numerical formats

IOT developers have a never-ending fountain of innovation, creating new concepts and pushing the boundary for enabling computers to interact with their boundaries. This innovation spills over into the constant creation of new numerical formats. I’ve created a system for dealing with a bunch of different Bluetooth values.

TL/DR:I8 U8 U8” means read three bytes, the first signed and the next two unsigned. “I8|DEC|Temp|c U8|DEC|Pressure U8|DEC|Humidity” means the same thing, but they should be displayed in decimal, they each have a name, and units of the first one is degrees Celcius. And for an example of doing math, ” I24^100_/ ” means read in a 3-byte (24-bit) number and divide it by 100.

History: big and little endian

One of the earliest hints of the many varieties of number formats is from the famous Internet Engineering Task Force note IEN 137 (IEN is Internet Experiment Note). That paper listed some of the numerical formats in use on internet-facing computer and proposed a partial solution to the common problem of sending integer data. This is the paper that started the big-endian (network and many then-popular computer) and little-endian (some computers including Intel chips) nomenclature.

The Internet as a whole, since the 1980’s, has decided that networks should generally send data in big-endian format. Most PCs are in little endian format. Mac computers have changed their default endian-ness. Bluetooth is little endian by default. But some devices (I’m looking at you, Witti designs!) has some big-endian values.

Examples of problematical numerical formats

For the unbelievers – the people who think that IOT devices are easily specified, and that there are just a few simple data types – here’s a brief list of a few of the formats I’ve needed to deal with

DataFormat
BBC Micro:Bit Temperature dataA single signed byte that represents the temperature in degrees Celsius. For example, when the value is 26, it means that the temperature is 26 degrees Celsius.
This is actually a pretty simple format, but the next two are much weirder.
InkBird IBS-TH1 Temperature dataA two-byte, signed integer which is in units of a hundredth of a degree C. The value must be divided by 100 to get standardized units of Celsius.
Nordic Semiconductor “Thingy:52” pressure dataTwo bytes in “12Q4” format: there are 16 bits total (12+4), and there’s an implied decimal point with 4 bits of precision. After that, the data must be divided by 1.25 to get a pressure in milliBars.
Texas Instruments 1350 SensorTag Pressure sensorThree bytes that are a signed integer that must be divided by 100 to get a pressure in hPA (hecto-pascals, or millibars. Standard atmospheric pressure is 1013.25 hPa)

In addition, many Bluetooth devices put multiple readings into a single characteristic. For example ,the ProtoCentral Sensything will put 4 different voltage readings into a single analog value, and it’s very common for environmental sensor to include humidity and temperature into a single characteristic.

Little Language for IOT Number Parsing

Requirements for the language

Because this little language will potentially be implemented by people in a hurry, the language must be trivial to parse. Most computer languages have a perfectly capable string-split capability; the little language lexical analysis should simply be some variant of strsplit. The language is a little more awkward as a result, but that’s an acceptable tradeoff.

Similarly, it’s simpler if each character (like the vertical bar, |) has only one meaning.

The language includes (in one part) reverse polish notation (RPN) style expressions to modify the incoming data. Most people strongly prefer to use the normal math operators (* / + -); those characters are reserved for the expression language and not used elsewhere. For example, “/” should not be used as a separator because that will interfere with it being used by the mathematical expressions.

The language will be embedded in JSON and may well be embedded in the future in a URL. Common URL characters should be avoided (# & @ ? 🙂 as should anything that can’t be in a JSON string (like a quote “ or the JSON string escape \ or CR or LF.

The final form of the language is:

  • There’s a set of fields separated by a single space. Extra spaces – either before, after or having multiple spaces – is an error.
  • Each field is further split into four sections by vertical bars. The first field is mandatory, and the rest are optional. Example: U8 is a field with just the first section and U8|DEC|Temperature|c is a field with all four sections
  • Each section is potential separated into sub-sections with a caret (^). For example, U16^100_/ is field with one section; that section is divided into two sub-sections. The first sub-section (U16) tells us that the number should be read as an unsigned integer; the second says that the value should be divided by 100.

Fields are separated with a single space

Bluetooth devices, luckily,always present data in a consistent way. I’ve never seen a device where the field sizes change from one sample to the next. It’s always that case that if some value is two bytes in on reading, it’s always two bytes. Devices often include multiple data fields in one characteristic. [Update in 2020: the GoDice people managed to mess this up. All events are channeled through the same mis-used characteristic. Each event starts with a variable-sized ASCII event type: “R” for “roll” but “Col” for Color]

Each field description is separated with spaces. Example: U8 U8 U8 would be used by a characteristic that includes three unsigned bytes, each of which needs to be handled separately.

In addition to real fields which describe specific bytes there are also pseudo-fields which provide per-characteristic information. For example, you might add the OEB (endian/big) pseudo-field if the data should be interpreted in a big-endian format. (There’s a corresponding OEL for endian/little, and it’s the default for Bluetooth). All pseudo-fields start with the letter capital-O.

Field sections + subsections

Each field will need a richer description than just U8, of course. There are four things that a program needs to know about each field:

  1. The numerical format
  2. The preferred display mechanism (e.g., decimal or hexadecimal)
  3. The preferred computer-friendly name (no spaces)
  4. The units. So far this has not been developed very far. A future goal is that when UI is automatically generated for the field, that that user will be able to select their preferred units. For example, many temperature sensors produce data in degrees C. Some users prefer to see temperatures in degrees Fahrenheit. Similarly, barometric pressure is often produced in hPa (hector-Pascals) millibars but users want to see the results in PSI (pounds per square inch).

These sections are separated with vertical bars (|). Example: U8|DEC|Temp|c is a field where all four sections are present. This value is an unsigned byte, the preferred output is decimal, the field should be called Temp, and the units are degrees c.

Each section is then split into sub-sections with a caret (^) symbol. Example: I24^100_/ is a field with a single section (the whole of I24^100_/) which has two sub-sections I24 (read in a signed 24-bit integer) and 100_/ (divide the value by 100).

The numerical format has two sub-sections. The first is the format proper (e.g., “I24”). The second is used by the calculation language (example, “100_/”). A complete example is “I24^100_/”.

Formats: Simple integer U<bitsize> and I<bitsize>

The I simple format describes signed and U describes unsigned integers. The number of bits must be evenly divisible into bytes; the only allowed values are 8, 16, 24 and 32. These are commonly also called bytes, words, an unnamed type and quadwords.

The endianness defaults to little endian but can be changed with the OEL (endian-little) and OEB (endian-big) pseudo-field.

Example: U8 is an unsigned byte (8 bits) with values 0..255.

Formats: IEEE floats F32 and F64

The F format describes IEEE floats. Both 32-bit and 64-bit floats (commonly called a “double” for historical reasons) can be read. The endian flag is used.

Formats: Q style fixed (floats) (example: Q12Q4)

The Q fixed-format system specifies two numbers: the number of (signed) integer bits and the number of fractional bits. The total number of bits must be 8, 16 or 32. The value is signed.

The difference between a “fixed” and “float” has to do with their range and flexibility. A fixed number can only be used when the range is known ahead of time. An accelerometer, for example, is often set to only provide numbers in a pre-set range like ±8 G. A float is auto-ranging; it can handle values in an enormous range with a certain level of precision. At the lowest level, floats are much more complex to deal with.

Example: Q6Q10|HEX|AccelX|G from the Nordic Things Raw Motion values. The Q6Q10 is a 16-bit value where the top 6 bits are the integer part of the acceleration (so it can be a value from 31 to -32) and the bottom 10 bits are the fractional bits.

Formats: / (slash) style fixed (example: /U8/P8)

The slash format is a subtle variation on the Q style fixed numbers. A slash-style fixed number has two parts: the integer part and the fractional part, each of which must be a simple integer value.

In the slash format, the integer part can be unsigned. The fractional part can be either a binary fraction (any of the unsigned simple formats) or can be a percentage (decimal) which is shown by using a P for the number (e.g., P8 for an 8-bit number which in reality will always be 0..99)

Example: /I8/P8|FIXED|Temperature|C is from the Nordic Thingy temperature reading. The value is a two-byte value where the first integer part is a signed byte and the fractional part is a byte where only the values 0..99 can be present and represent a decimal fraction. If the incoming hex is 0x1B23, the 0x1B is converted to 27 degrees Celsius and the 0x23 is converted to .35; the final value is 27.35 degrees.

Note that the string representation of the number will correctly match actual value (it will be displayed as 27.35 and not 27.350001)

As a weird quasi-historical note: the slash (/) format was implemented first and then the Q format had to be created. If this mini-language was recreated, I’d be tempted to jam everything into the Q format.

Formats: BYTES (example: BYTES)

The Bytes format is just what it appears to be: a hunk of bytes, generally represented as a series of hex-encoded bytes. It can be of any length (indeed, there’s no current way to force a particular number of bytes, which will have to change)

Formats: STRING (example: STRING|ASCII)

The string format is more challenging than bytes thanks to multiple common representations of strings in IOT devices. The length of the string is “all the rest of the bytes”

The string will be decoded as if it’s a UTF8 string. If the incoming bytes cannot be decoded as UTF8, they will instead be read as HEX and displayed in a HEX format.

If the display format is default or ASCII, the display string will have nulls converted to backslash-zero (“\0”), CR and LF converted to \n and \r, vertical tab to \v, and plain backslashes to double-backslash \\. Yes, using the word ASCII in this context is a little confusing since the original string was might have been UTF8, and the resulting string will be displayed as UTF8.

If the display format is Eddystone, the string will be converted as an Eddystone-encoded string. For example, if the first byte is a NUL, it will be replaced with the characters “http://www.”

Pseudo-format: O option

Any field starting with an uppercase O is an option pseudo-field. A pseudo-field doesn’t represent data in the incoming bytes; instead it says how the data should be parsed in a broader context. For example, some Bluetooth characteristics needs to be parsed in a big-endian format; rather than have a special tag on each field, the endianness set by a pseudo-option (OEB for option-endian-big in this case).

Endian OEB (endian=big) and OEL (endian=little)

Sets the parsing from that point on to be either big-endian or little-endian. Networking is overwhelmingly big-endian (for historical reasons); Bluetooth LE uses little-endian. Because this library is commonly used with Bluetooth, it defaults to little-endian.

Optional OOPT

Some fields are optional. Use this flag to indicate that the rest of the fields in the incoming data are optional and should be filled in with default values.

TI 1350 SensorTag 2.0: Barometer is “OEL I24^100_/” meaning: read in a 3-byte signed integer in little-endian format. Then divide the result by 100. The data beyond the ^ is the set of math commands to be performed on the data; there’s an RPN stack-based turning complete language to perform calculations.

The display portion can be either HEX for DEC to indicate whether the value is commonly displayed in decimal or hex values.

BBC micro:bit: The thermometer data is I8|DEC

The value is a single signed byte and typically displayed as decimal. For example, a course-grained temperature reading might use this format.

Calculation Language

Each numeric field can be modified via a reverse polish notation (RPN) expression language. The calculation expression is the second sub-field in the numerical format section.

The example I24^100_/ will be used as the sample numerical format section. The I24 is the first sub-section and says that three bytes (24 bits) of the incoming data will be read as a signed integer. The 100_/ is the calculation language.

The calculation language is a stack-based language. The starting value (from the I24) is the first entry and only entry in the stack. The stack only contains double-precision floating-point numbers.

The language is split by underscores into two items: 100 and /. The 100, being a number, is pushed onto the stack. The / means a floating-point divide. It uses up two items from the stack, divides them (the divisor is the one at the top of the stack – 100 in this case), and then pushes the result onto the stack.

There are four opcodes: + – * /. These represent their normal math meanings.

Each command is exactly two upper-case letters.

Command
+ Opcode
Meaning
numberValue to push onto the stack
+ – * /Opcode for normal math. 10_2_- is the same as 10-2
ANAND the 2 top elements
DUDUPLICATE the top element
GOGO TO a command
IVINVERT inverts the value (e.g., 3à-3 and -3à3)
JN JZ JUJump if non-zero; jump if zero; jump unconditional
LS RSLEFT and RIGHT SHIFT
NONO-OP; does nothing
POPOP
SWSWAP top two elements
XY YXYX calculate y**x where x is the top of the stack.

 

XY calculates x**y where x is still the top of the stack

Example 10_2_YX is 10^2 = 100 and 10_2_XY is 2^10 = 1024

ZELike AND but the top value is inverted. 0xFFFF_3_ZE is 0xFFFB (bottom 2 bits are zero’d)

Display format section (examples: DEC HEX FIXED)

The display sections says what the ideal display type is. For example, humans often want to see a temperature value displayed in a base-10 number, not in hex.

For numeric values, you can specify DEC or HEX. For fixed and floating point numbers (like those produced by the Q, slash, or F numerical formats), use FIXED. For strings, display format can be ASCII or Eddystone.

The Specialty display format is used when a value might be a specialized value like an enum. The particular specialization must be added to the sub-section. The only supported value is Specialty^Appearance which will convert a number into a Bluetooth appearance value (e.g., 64 is Phone)

Name section (example: Temperature)

The name section specifies a name for the field.

Example: In the field U8|DEC|Temp|c the field name will be Temp.

Units section (example: mbar)

The units section is a hint about the actual units for the field. This isn’t currently standardized. Some common values are

Amount: ppb (parts per billion)
Angle: d (degrees) dps (degrees per second)
Battery level: %
Gravity: g mpss (meters per second per second)
Light: Lux
Magnetization: microTesla
Pressure: hPa
Transmit Power: db db_at_1_m
Temperature: C
Time: s ms (milliseconds) 10ms
Voltage: volts

 

Why me, and why now?

I’m doing this because I need it, and I don’t see any other mini-language that can express the reality of modern Bluetooth devices.

There are existing libraries for serializing and deserializing data. Many existing serialization packages carry a strong assumption that the serialization code is the owner of the permanent data format. The packages assume that there is only a small number of numeric types, and that the programmer isn’t concerned with their exact representation so long as the representation is robust and is multi-platform. IOT is the opposite: there are many numerical formats, some of which are different from all previous ones.

I’m creating a hobby program that lets me investigate and use a variety of Bluetooth sensor devices. This is not my first foray into the morass: I have an existing set of app available on the Microsoft app store to deal with a variety of sensors and lights, and I have an existing IOT-capable computer language built into a moderately popular calculator program, also on the Microsoft app store.

One of the top goals of the latest project is to stop rewriting the Bluetooth code. At this point, I have a large enough corpus of actual Bluetooth devices that I can create a JSON description of each devices services and characteristics and use each description to generate both foundational protocol code and “good enough” UI code that a moderately capable programmer can customize. That JSON description includes a little language to describe exactly how each data field should be parsed.

August 23, 2019 / shipwrecksoftware

Simple Gopher Client

Gopher is one of the most ubiquitous of all of the Network interfaces, and now a Gopher client is available on the Windows Store!

When you start the Simple Gopher Client, you’ll see a screen like this:

10_Main_Screen

A Gopher page is very similar to a Web page like you’d see in Chrome (or Edge!), but it’s designed for simplicity. There’s no giant ad networks sending you hundred of megabytes of ad, no distracting animations, and almost no corporate involvement. What you will find is a community of people.

Each of the folder icons is a link to a different page; click it to display a new page. Other icons include the

  • 🖼 (picture) to display a picture (PNG GIFs are supported)
  • 🔎 (magnifying glass) to start a Gopher search
  • 🗎 (text) to display a text file
  • 🌏 (globe) is a link to a web page
  • ␑ (binary) to download a binary file

Gopher search is very different from Web searches. A Web search is done by a big company like Microsoft or Google; a Gopher search is just done by the company whos page you are on. Sometimes that will be an all-encompassing search, and sometimes that will be just for the site.

Each time you click a link, you’ll get a new page on an ever-increasing scrolling list of places you’ve visited in that session. Each site has a maximum amount of screen size that you can see (but you can always scroll to see everything).

90_Scrolling_Results

Example showing two Gopher screens.

Each screen has a menu with a File and Close button. Close just closes the screen. The 40_FileFile menu lets you

  • add this particular Gopher screen to your favorites list
  • reload the Gopher screen
  • save the content as a file (something that lots of web sites don’t let you do these days!)
  • close the Gopher screen

Adjusting the Simple Gopher Client

You might sometimes need to change how the Simple Gopher 30_OptionsClient works. The Options menu lets you do just that.

You might prefer a different font or font size; use the drop-down list to select a different font or font size. All of the screens will be updated right away.

Simple Gopher Client has a maximum download size; this is normally set to be 500000 bytes of data. The download size affects all downloads, including downloads of binary files. If a file is too large to download, you can increase the maximum download size as needed.

Lastly, modern Gopher servers are all very fast. There’s no need to wait…and wait…and wait to see your data (last time I checked my mail, the web interface didn’t want to show me anything for almost a minute!). Simple Gopher Client assumes that if a server can’t respond in 5 seconds, it’s got a problem and will never respond. If you routinely connect to a slow server (or are connecting via a very slow internet connection), you can increase the timeout size.

 

 

 

 

 

 

February 24, 2019 / shipwrecksoftware

Common Privacy Policy

Rather than have a different privacy policy for each program, going forward most Shipwreck Software programs will use this one common privacy policy. As always, Shipwreck Software doesn’t deliberately track you (but for apps that include advertising, the advertising networks might).

Network Usage:

In common with many modern apps, this app may offer or use various network-related
services. These may include special news items and forums, feedback mechanisms to give information back to the developer, and also may display ads.

Data Collected:
This program does not deliberately collect personal data. It does not ask for your name or email address, and does not knowingly send them back to the developer. Network usage does automatically mean that your IP address (or your gateway’s IP address) will be transmitted to the developer.

How we use the data:
Your IP address may be logged as part of normal server operations. Requests and suggestions that you make may be incorporated into the product with no compensation. In addition, the program may display ads; the ad provider will have their own privacy policy. We do not sell your personal information.

Roaming data:
The program saves its state as roaming data; this means that the data will be sent to other computers that you log into. This is the standard Windows process; that data is not sent to the developer.

Security:
The developer will take ordinary precautions against unauthorized access to information provided.

Ad networks:
Many Shipwreck Software apps are supported by ads from Microsoft Advertising or other similar advertising networks. Learn more about Microsoft’s privacy practices and your choices. Learn more link: https://choice.microsoft.com/AdvertisementChoice/

January 26, 2019 / shipwrecksoftware

Atmosphere IOT Variables

Hackster.IO, NXP, Rapid IOT Contest

I’m having fun with an NXP Rapid IOT device and the Atmosphere on-line IOT program designer. I found it through a contest at Hackster.io. In the past I’ve connected these sorts of devices up to Windows, either writing a custom program which I then put on the Windows App Store, or more recently I create a Bbluetooth module in my Best Calculator program so that the devices can be programmed from BC BASIC. This doesn’t work with the NXP Rapid IOT devices; I can’t get it to pair with Windows. So my programming is all in the Atmosphere IOT on-line editor.

The good, the bad

The good is the amount of polish the Atmosphere people have put into their editor. The whole system is a fine piece of technical work; it’s fast and has a lot of easy to access functionality. It’s easy in this day and age to make a slow, painful HTML + JavaScript system.

The downside is that it’s all GUI plus weird code-behind. The GUI does what it can, but the simple and fun looking “hello world” quickly degenerates to this:

atmosphere_iot_example

mr-gruff-bigger

Me as Mister Gruff when I use the GUI programming system.

Look at that mess! There’s loops, and swirls, and it really not clear what’s going on, or how to access almost anything. Worse, the Atmosphere documentation is woefully underspecified; they seem to think that just because somewhere there’s a sample that somewhere in the rats-nest of lines some concept is demonstated that the documentation is good enough. Bah!

As soon as you leave GUI, there’s just a big lump of code with hardly any editing abilities. I’ve been obliged on several occasions to copy the whole thing over to Notepad++ to quickly research how the code actually works!

IMHO, this is part of a bigger problem with GUI programming: it works until it doesn’t, and that happens much faster than with most systems.

All about global variables

Here’s how the global variables in Atmosphere work. The key concept is that the variables is wrapped by an ordinary function. In the rat’s nest pictured above, there’s a variable called  UserTempStorage. It’s an Atmosphere-type function (a square with a somewhat squared-off sine wave). Atmosphere also has “variables” (squares marked with (v)), but this sample doesn’t use those.

What is an Atmosphere-type function? Each of the little icons in the GUI is represented by a single function that takes in two variables of type ATMO_Value_t *. One is called in and the other out. The function returns an ATMO_Status_t which should always be ATMO_Status_Success. There might be other return values, but I’ve never seen one, and it’s not documented what happens when you return something that isn’t success.

The Atmosphere system is strongly event driven; you’re supposed to “wire up” the blocks together. There might be a block which is a timer, which drives the accelerometer, which in turn drives a function, which drives a line on the display.

In the case of the CalcThermostatHeating function, events come in from the RealTempStorage function, the IncTemp function and the DecTemp function.  That is, when the desired temperature is increased or decreased, or the current real temperature changes, the thermostat is recalculated. The trick is that normally we use the actual inputs to the function (the in value) in the calculations, The CalcThermostatHeating function does not follow this typical pattern. It completely ignores the inputs event value. Instead when an input event happens (of any type), it completely recalculates the amount of heating needed. Here’s how.

The CalcThermostatHeating will first get the Real temperature by calling the RealTempStorage function. This is the function that is normally called via the fancy event system. As it turns out, you can also just call it. You can pass in an “in” value or an “out” value (or both) and the value will be set or gotten (or both).

This is the code that gets the Real and User temperatures. The final goal is to get the realTemp and userTemp as integer values. To go that, you have to call RealTempStorage_trigger, passing a NULL for the input and &atmoRealTemp for the output.

unsigned int realTemp, userTemp;
ATMO_Value_t atmoRealTemp, atmoUserTemp;
RealTempStorage_trigger(NULL, &atmoRealTemp);
UserTempStorage_trigger(NULL, &atmoUserTemp);
ATMO_GetUnsignedInt(&atmoUserTemp, &userTemp);
ATMO_GetUnsignedInt(&atmoRealTemp, &realTemp);

By calling RealTempStorage_trigger (remember, this is a generic “function” created in the GUI) with just an output, the value is gotten as an ATMO_Value_t. You then pull the value out as an unsigned int with ATMO_GetUnsignedInt.

Yes, this is clumsy and not particularly obvious. One of the big downsides to GUI programming systems is that sometimes it’s possible to do common actions (like geta saved global value), but it’s not obvious like it is in most system.

In BC BASIC, by the way, in  function you can access a global variable by just saying that you’re using a global: GLOBAL RealTemp. I like my little BASIC system, and miss it for this project!