Bicycle computer XOSS Nav Plus review

As an active cyclist, I'm always looking how to enhace my rides. One of the option is to have navigation available. You plan route in advance and you just execute it on the road. For this reason I was looking for bicycle computer, that would have GPS and could lead me on the road. Basicly, there are two ways how navigation could be executed: just breadcrumb of your path and highlighted path on maps. Having offline maps in liquid screen display was tempting. After some research I've decided to try XOSS company NAV+ device as my bicycle computer.

  • Dimension: 88mmx55mmx19mm
  • Weight: about 67g
  • Screen: 2.4 inch
  • Resolution: 240×160
  • Battery: 600mAh rechargeable lithium battery
  • Working temperature: -10~50 ℃
  • Waterproof level: IPX7
  • Battery life: 33h in standard mode; 40h in low-power mode (affected by usage environment and temperature)
  • Charging interface: USB-C
  • Memory Capacity: about 10,000 hours
  • GNSS support (GPS, Galileo, Beidu)
  • BT and ANT+ sensors
  • Offline maps
  • Various metrics

The XOSS NAV+ arrived in a well-packaged box, including mounts, a USB-C charging cable, and the main unit. The device uses Garmin-type mounts for easy attachment. Pairing with the mobile app was straightforward, and I also purchased additional accessories like a protective case and compatible sensors for speed and cadence, which were easy to set up.

I've rode few 100's kilometer before writing this review, so everything is from my experience.

  • Liquid crystals display- clear to seen in bright light. Screen also has backlight, if needed;
  • Beeping is loud enough to be heard durind busy city riding;
  • GPS is accurate and connects to sattelite within 5 seconds. Mob app updates this when required, and you can force refresh if needed;
  • Offline maps is accurate and shows most of paths. You can zoom in/out the current location, but you can not pan to sides to look around;
  • Plenty of batery for multiple rides. It's is declared 33hours. I would not say that this endurance is possible, I would say 20-25 hours. Have not tested it though;
  • Connects to XOSS Vortex speed and cadense sensors and Garmin heart sensor without issues;
  • Route planning functionality inside applications works good. It also accepts GPX files (maybe some other types also) then you can upload path to device. There are plenty pre-made by comunity, that you can upload to device and ride.
  • Map is always north oriented, not possible to rotate according riding direction;
  • Map doesn't update, if you did not start tracking, even if the maps screen is not open;
  • You can have up-to 20 routes, uploaded to device. Routes does not have name, only numeric ID- so sometime it is dificult to understand which route is the needed;
  • Odometer is not moving, if not started tracking, even if speed sensor is connected. Speed is shown on screen, but odometer do not move;
  • Imposible to reset odometer, so if handed over to a friend- it's not possible to start from fresh;
  • Charging does not start, if i don't turn-on device. Tested with USB power meter- battery simply does not fill. Ihave to turn it on, device starts charging itself, and then I can turn it off and leave it to charge;
  • When managing layout, there are some layouts in mobile application, when transfered to device- metrics shown switched places.
  • Does not show any notifications from mobile phone on call or message;
  • Very slow map transfer speed into device. Speed of the copying is about 300kb/s;
  • Can not change GNSS configuration, it always stays GPS+Beidu;
  • Once had a glich, that computer started, but screen did not shown anything. Just heard from the beeps that device active. Managed to shut-down and start again- it started normally;
  • Missed possibility to track gear, how my kilometers rode with chain or tires or whatever you would like to track;

While there are several software-related issues that could be improved, the XOSS NAV+ is a solid and budget-friendly choice for cyclists. It may not match high-end Garmin or Hammerhead models, but for €60, it adds significant value to your rides. Considering its features and performance, I would rate it 8/10.

2024/06/10 18:59 · Ignas · 0 Comments

MPY-CROSS: The ultimate MicroPython precompilation tool. Download available

MicroPython is a straightforward and effective Python version created for microcontrollers and other devices with limited resources. One of MicroPython's key features is the ability to execute Python code that has been precompiled to bytecode, which can help the interpreter operate better and consume less memory.

Mpy-cross is one of the programs that is most frequently used to precompile Python code for MicroPython. With the help of this command-line utility, Python code created in a MicroPython program can be translated into bytecode that can be run on a device that supports MicroPython. iteration 6 of mpy-cross is the most recent iteration. This version has bug fixes and additional features.The main feature of this version is that it supports the latest version of MicroPython and it includes a new option to control the optimization level of the generated bytecode, which can help to reduce the size of the generated code and improve performance.

Another feature is that it now supports the compilation of Python modules, which can be used to improve the performance of the interpreter and reduce the amount of memory used by the program. Additionally, mpy-cross can be used to create standalone MicroPython executables that can be run on devices without a full MicroPython installation.

Using mpy-cross is very simple. Once you have installed the tool, you can use it to convert Python code into bytecode by running the following command:


Full information about its capabilities is available in help text bellow:

usage: mpy-cross-6.exe [<opts>] [-X <implopt>] <input filename>
--version : show version information
-o : output file for compiled bytecode (defaults to input with .mpy extension)
-s : source filename to embed in the compiled bytecode (defaults to input file)
-v : verbose (trace various operations); can be multiple
-O[N] : apply bytecode optimizations of level N

Target specific options:
-msmall-int-bits=number : set the maximum bits used to encode a small-int
-march=<arch> : set architecture for native emitter; x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin

Implementation specific options:
  emit={bytecode,native,viper} -- set the default code emitter
  heapsize=<n> -- set the heap size for the GC (default 2097152)

In addition to the performance benefits, mpy-cross is also a useful tool when working with MicroPython scripts that are short on RAM memory. When running a MicroPython script, the interpreter must load the entire script into memory in order to execute it. This can be a problem for devices with limited RAM, as it may not be able to load large or complex scripts.

By precompiling the script using mpy-cross, the size of the script is reduced, which means that less memory is required to load and execute the script. This can be particularly beneficial when working with memory-constrained devices, such as those with limited RAM or flash storage.

For example, if you have a script that is using up all of the available RAM on your device, you can use mpy-cross to precompile the script and see if that reduces the amount of memory used by the script. You can also use the new option to control the optimization level of the generated bytecode, which can further help to reduce the size of the generated code and improve performance.

In summary, mpy-cross is a valuable tool for MicroPython developers working with memory-constrained devices. By precompiling Python scripts into bytecode, it can help to reduce the amount of memory required to load and execute the script, which can improve the performance of the device and enable the execution of more complex scripts.

The -O option is a command-line switch that can be used when running mpy-cross to control the level of optimization that is applied to the generated bytecode. When using this option, you can specify a numerical value from 0 to 3, with 0 indicating no optimization and 3 indicating the highest level of optimization.

The higher the optimization level, the more aggressive the optimization will be. At level 3, the mpy-cross will try to make the code as small as possible and run as fast as possible, but this may increase the compilation time.

The optimization level can have a significant impact on the size and performance of the generated bytecode. For example, at level 0, the generated bytecode will be larger and may run slower, while at level 3, the generated bytecode will be smaller and may run faster.

The default optimization level is -O2, which provides a good balance between code size and performance. If you are working with a device that has limited flash storage and/or RAM, you may want to try using a higher optimization level, such as -O3, to reduce the size of the generated bytecode.

It's worth noting that when you are using mpy-cross to compile modules, the -O option applies only to the module and not to the whole project.

In summary, the -O option in mpy-cross is used to control the level of optimization that is applied to the generated bytecode. By specifying a numerical value from 0 to 3, you can determine how aggressive the optimization should be and make trade-offs between code size and performance. Keep in mind that the default optimization level is -O2, which provides a good balance between code size and performance, and if you are working with a memory-constrained device, you may want to try using a higher optimization level to reduce the size of the generated bytecode.

always check all your files for viruses

MicroPython release.mpy versionVirusTotal report
v1.19 and upVersion 6Read
v1.12 - v1.18Version 5Read

Host your website at home

If you want to share your thoughts, ideas, or business with the world, setting up your own website is a great way to do it. While there are many hosting options available, hosting your website from home can be a cost-effective and convenient solution. By following these steps, you can set up a local network and host your own website with a few simple tools and some basic technical know-how.

Before you get started, you will need to make sure you have the right hardware in place. Here are the basic requirements for hosting a website at home:

A computer: This will be the server that hosts your website. It needs to be stable, reliable, and connected to the internet via a wired or wireless connection. Ideally, you should choose a computer with a fast processor and plenty of storage to ensure that your website can handle a large number of visitors. In most cases, any Raspberry Pi single board computer should be OK for entry stile website-blog.

A router: This device creates a local network, allowing multiple devices to connect to the internet and communicate with each other. There are many different router options available, ranging from basic models to more advanced ones with additional features such as parental controls and guest networking.

A domain name: This is the unique address that people will use to access your website on the internet. You can purchase a domain name from a registrar, such as GoDaddy or Namecheap. Choose a domain name that is easy to remember and reflects the content of your website.

A domain name is a unique address that people use to access your website on the internet. It acts as a human-readable label for your website's IP address, which is a series of numbers that identifies your server on the internet.

There are several reasons why a domain name is required when hosting a website:

  • A domain name makes it easy for people to find and remember your website. Without a domain name, people would have to remember a long string of numbers in order to access your website, which is not only difficult but also not very user-friendly.
  • A domain name gives your website a professional look and feel. By using a domain name that is related to your business or personal brand, you can establish credibility and make a good impression on your visitors.
  • A domain name can help you rank higher in search engine results. Search engines tend to give preference to websites with a relevant and well-known domain name, which can help drive more traffic to your website.
  • A domain name can protect your brand. By registering a domain name that is similar to your business name or brand, you can prevent others from using it and potentially confusing your customers.

Overall, a domain name is an important investment for any website owner. It helps establish your online presence and makes it easier for people to find and access your website.

You have to take care of security very seriously, as you are opening access to wide world. Having default passwords and insecure software leaves you and your server vulnerable.

To create a local network, you will need to connect your router to your modem and configure it according to the manufacturer's instructions. This typically involves accessing the router's web-based configuration page and entering your network name (also known as the SSID) and password.

You may also need to configure additional settings, such as the type of encryption used to secure your network or the frequency of your wireless signal. Consult your router's documentation or online resources for specific instructions.

In order for your website to be accessible from the internet, you will need to assign a static IP address to your server. This will ensure that your website can be found at the same address every time someone tries to access it.

To assign a static IP address, you will need to access your server's network settings and specify a fixed IP address. This may vary depending on your operating system. On a Windows computer, you can assign a static IP address by going to “Control Panel” > “Network and Internet” > “Network and Sharing Center” > “Change Adapter Settings” > “Properties” > “Internet Protocol Version 4 (TCP/IPv4)” > “Properties” > “Use the following IP address.” On a Mac, you can assign a static IP address by going to “System Preferences” > “Network” > “Advanced” > “TCP/IP” > “Configure IPv4” > “Manually.”

Most routers have a built-in firewall to help protect your network from external threats. You will need to configure your firewall to allow incoming connections to your website. This typically involves creating a “firewall rule” that allows traffic on a specific port to pass through the firewall.

In addition to configuring your firewall, you will also need to set up port forwarding, which directs traffic from the internet to your server's IP address. This is typically done through the router's web-based configuration page, where you can specify the port number and the local IP address of your server.

For example, if you are using Apache as your web server software and want to host your website on port 80, you would create a firewall rule that allows incoming traffic on port 80 and set up port forwarding to direct traffic on port 80 to your server's IP address.

There are many different options for web server software, including Apache, NGINX or LightTPD. Once you have chosen a web server, you will need to install and configure it according to the manufacturer's instructions.

Depending on your web server software, you may need to create a virtual host configuration file, which specifies the domain name and document root of your website. You will also need to place your website's files in the appropriate directory on your computer.

Once you have set up your web server and configured your router and firewall, you should be able to access your website from a browser on a device connected to your local network. You can also use a tool like “What's My IP” to verify that your website is accessible from the internet.

Remember to keep your router and computer secure by using strong passwords and keeping your software up to date. With a little bit of planning and setup, you can easily host your own website from the comfort of your own home.

View saved WiFi password on windows

Have you ever wanted to know password that was entered on your computers? Here is and easy way, no need to install. Everything is build-in windows to provide you this information.

Open Command Prompt (start → run → cmd)

netsh wlan show profile

You'll get a list of Wifi's, that you have ever connected. To get password of particular wifi, type following command:

netsh wlan show profile MyWifiName key=clear

just change MyWifiName to something from your list. In “Security settings” group, Attribute “Key Content” you'll see a password saved in your OS.

2022/08/11 12:16 · Ignas · 0 Comments

Push Notifications on Droidscript

NOTE: Proof Of Concept

So, you are developing DroidScript application and your requirement is to send Push-Notifications to user phone. Also, you want to handle correctly those notification messages, so each message would have different outcome: open particular page on your app or do whatever is needed.

Looks like there are some options not to use Google Firebase infrastructure for notifications, but get away with other tool. As this project is more of PoC- there will not be very mature back-end solution or front end. This project is more like showing the way how Push-Notifications can be implemented in you DroidScript app. Obviously, there are more solutions available, and I assume each one witch supports JavaScript should work. But we are learning, so it good to know basics.

This project is to let you understand what it basically needed to have this functionality. No paid tools or licenses are required, event for testing purpose no back-end hardware is required- Public free options can be used.

Basic concept of a project is following: there is Droidscript application, it has Service that runs on background. Service utilise MQTT protocol for receiving messages and creating Android Push-Notifications. Clicks on notification is handled by Main application. Each client should subscribe to unique topic (for PoC I simply used topic notification). Then back-end engine should send messages to required topics.

For MQTT messages, you can fire up your own MQTT Broker or use the Public one. Droidscript MQTT plugin work by communicating with broker user Web Sockets. Wikipedia: WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C

This is not needed if you want to test with public brokers. You can skip this part

If you have chosen to set up your own hardware- please follow this write-up further. For this example I use Mosquitto (by Eclipse) software broker that works on mostly any hardware and operating system.

Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.

My hardware is Raspberry Pi 2B+. The same broker can be used in IOT projects, for example with ESP32 to send you sensors value. Here I will cover configuration required for Web Sockets and MQTT Broker. How this can be installed search here. If you are on linux, after installing broker you need to chaneg configuration. Edit following file with a command sudo nano /etc/mosquitto/mosquitto.conf or any other way you like it.

# if you need to have closed system- you need to
# provide were login details are saved
# if allow_anonymous is set to false
password_file /etc/mosquitto/public/public.passwd
listener 1884
allow_anonymous false

# web sockets configuration
listener 9004
protocol websockets

After changing configuration, you should be able to connect to your Broker via MQTT. For checking it, you can use HiveMQ WebSocket Client. Provide your broker IP, port (and login if needed). If it connects succesfully, you can subscribe to topic $SYS/# Here you will get all statistics how your Mosquitto is running.

The next step is to prepare software side. To work with MQTT- plugin is needed that is can be downloaded from droidscript application. Install it

Create new JavaScript application in your DroidScript . Your project must have two files: main file that is named after you project, and another, named “Service.js”. This tells your DroidScript application to run Service.js as Android service and listed for DroidScript messages.

//Called when application is started.
function OnStart()
    //Start our service.
    svc = app.CreateService( "this","this", ()={
        // On service ready
        console.log( "Service Ready" );
    svc.SetOnMessage( OnServiceMessage );
    //This will cause your service to start at boot.
    //(Set it to "none" if you need to stop it starting)
    app.SetAutoBoot( "Service" );
    var id = app.GetNotifyId();
    if( id ) HandleNotification(id);
//Called when application is resumed.
//(eg. When user returns from home screen)
// or after notification is clickeed while app was open
function OnResume() {
    app.ShowPopup( "On resume!", "Short" );
	var id = app.GetNotifyId();
    if( id ) HandleNotification(id);
function HandleNotification(id) {
    app.Alert( id, "Notification ID" );
//Called when messages comes from our service.
function OnServiceMessage( msg ) {
    console.log( "Service Message: " + msg );

Here is code for your service file. File must be named exactly this way to make it work as Android service

app.LoadPlugin( "MQTT" );
//Note: When running background services on newer Huawei phones, you
//may need to go into the Android battery saving settings and enable 
//DroidScript to run in the background if you want background 
//notifications to work when the phone is locked.
//Called when service is started.
function OnStart()
	//Force service to foreground on newer devices (required).
	if( app.GetBuildNum() > 25 ) {
        app.SetInForeground( "Waiting for notification...");
	// my private mosquitto configuration
	var mosquitto_options = {
    		host: "",
    		port: 9004
    	keepalive: 1800,
    	username: "myUser",
    	password: "myPass",
    // Unique identifier for each device
        mosquitto_options.clientId = "Android-" + app.GetDeviceId()
        mosquitto_options.clientId = "IDE-" + app.GetDeviceId()
    // Public mosquitto connection
    // client = mqtt.connect( 'ws://' );
    client = mqtt.connect( mosquitto_options );
    client.on( 'connect', ()=>{
        client.subscribe( 'notification', {qos:2} );
        // send client id as message to topic "clients"
        client.publish("clients", mosquitto_options.clientId)
    // create Android notification when MQTT message arrives to subscribed topic
    client.on( 'message',  (topic, message)=>{
        not = app.CreateNotification();
            "MQTT "+topic,
            "Msg: " + message,
            "Message: "+ message
        not.Notify( message );
        client.publish("heartbeat", new Date().toLocaleString())
    }, 60000)

Word of warning- android system limits web services. In my POC i've set up message publication each 1 minute to HeartBeat topic, so I would know how service behaves under the hood. On Android 11 Samsung device, at first it sends message each 1 minute, but later gradually increasing time between hear-beets. On my test average is 7 minutes. Looks like it does work correctly and on receiving MQTT message- prepare notification. Sure, if you unlock your device, heartbeat is sent each minute. You may need to play around with various battery optimisation setting for your application.

There are various MQTT protocol settings (Retained and QoS) may ensure that message is received even if device is disconnected upon sending notification message to broker from back-end. Client will get it when it connect to it unique topic.

Older entries >>

  • blog.txt
  • Last modified: 2023/11/07 13:33
  • by Ignas