0% found this document useful (0 votes)
364 views

Ovms Commands

OVMS stores configuration parameters in a standardized format accessed by the 'config' command. Each parameter has readable and/or writeable attributes set by its owner to control access. The CANopen protocol uses PDO, SDO, NMT, SYNC, and EMCY communication objects. To detect CANopen nodes, the OVMS issues NMT resets to trigger bootup messages and scans node IDs to access standard attributes from responding nodes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
364 views

Ovms Commands

OVMS stores configuration parameters in a standardized format accessed by the 'config' command. Each parameter has readable and/or writeable attributes set by its owner to control access. The CANopen protocol uses PDO, SDO, NMT, SYNC, and EMCY communication objects. To detect CANopen nodes, the OVMS issues NMT resets to trigger bootup messages and scans node IDs to access standard attributes from responding nodes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 65

1.

bms

2. can

3. charge

4. climatecontrol

5. config
OVMS stores all it’s configuration in a standardised protected configuration area accessed by
the ‘config’ command. The configurations are organised as follows:
<parameter> <instance> = <value>

For example:

Each parameter can be defined (by the component that owns it) as having readable and/or
writeable attributes, and these act as access control for the parameters.

 A ‘writeable’ parameter allows values to be created, deleted and modified.


 A ‘readable’ parameter allows values to be seen. Instance names can be seen on
non-readable parameters (it is just the values themselves that are protected).

For example, the ‘vehicle’ parameter is readable and writeable:

OVMS# config list vehicle


vehicle (readable writeable)
id: MYCAR
timezone: HKT-8

But the ‘wifi.ssid’ parameter is only writeable:

OVMS# config list wifi.ssid


wifi.ssid (protected writeable)
MYSSID
MyOtherSSID
MyNeighbour
You can add new instances to parameters simply by setting them.

Beginning with firmware release 3.2.009, a dedicated configuration section usr is provided for
plugins. Take care to prefix all instances introduced by a unique plugin name, so your plugin
can nicely coexist with others.

6. copen

6.1 CANopen

Communication Objects

A CANopen network consists of “masters” and “slaves”, masters are clients, slaves are servers.
At most one master may be active at a time.

CANopen supports addressing of up to 127 slaves on a bus using node IDs 1-127. Node address
0 is used for broadcasts to all nodes. Node addressing is simply mapped onto CAN IDs by
adding the node id to a base ID.

The CANopen protocol mainly consists of…

PDO (process data objects)

SDO (service data objects)

NMT (network management)

SYNC (synchronisation)

EMCY (emergency events)

PDO are regular, normally periodical, status update frames, for example sensor data. You can
log them using the CAN monitor ( can  log  start  monitor  … ). PDOs can be sent at any CAN ID
except those reserved for other CANopen services.

SDO are memory registers of nodes that can be read and written by masters on request. SDO
requests are normally sent at ID 0x600 + nodeid, responses at ID 0x580 + nodeid. SDOs are
addressed by a 16 bit index + 8 bit subindex. Registers and data types for a given device are
documented by the device specific object dictionary, normally represented as an EDS
(electronic data sheet) file.

NMT are short datagrams to control node startup / shutdown. There’s a special node state
“pre-operational” allowing access to all operation and communication parameters of a node in
a standardized way. NMT requests are sent at ID 0x000, responses and unsolicited updates
(aka heartbeats) are sent at ID 0x700 + nodeid with length 1.

SYNC messages are datagrams of length 0, normally sent at ID 0x080.

EMCY messages are sent if a node encounters some kind of alert or warning condition, they
are normally sent at ID 0x080 + nodeid with a length of 8 bytes.

CAN IDs Communication objects


0x000 NMT requests
0x080 SYNC
0x081 - 0x0FF EMCY
0x581 - 0x5FF SDO responses
0x601 - 0x67F SDO requests
0x701 - 0x77F NMT responses / heartbeats
So if any of these IDs look familiar to you, chances are you’ve got a CANopen network.

Note:

CANopen coexists nicely with OBD-II and often does in a vehicle (i.e. Renault Twizy). OBD-II
devices normally are addressed at IDs > 0x780 so are outside the CANopen ID range. Even if
they use non-standard IDs, the devices normally will detect and ignore frames not matching
their protocol.

SDO Addresses

The SDO address space layout is standardized:

Index
Object
(hex)

0000 not used

0001-001F Static Data Types

0020-003F Complex Data Types

0040-005F Manufacturer Specific Complex Data Types

0060-007F Device Profile Specific Static Data Types

0080-009F Device Profile Specific Complex Data Types


Index
Object
(hex)

00A0-0FFF Reserved for further use

1000-1FFF Communication Profile Area

2000-5FFF Manufacturer Specific Profile Area

6000-9FFF Standardised Device Profile Area

A000-BFFF Standardised Interface Profile Area

C000-FFFF Reserved for further use

For example, a device shall tell about the PDOs it transmits or listens to, their IDs, update
frequency and content structure at SDO registers 1400-1BFF. This is mandatory in theory but
real devices may not fully comply to that rule.

CANopen compliant standard device types like motor controllers need to implement some
standard profile registers. See CiA DS401 for the generic I/O device class definition and CiA
DS402 for motor controllers.

Most devices will require some kind of login before allowing you to change operational
parameters. This is also done using SDO writes, but there is no standard for this, so you’ll need
to dig into the device documentation.

Of course there’s a lot more on CANopen, but this should get you going.

CAN in Automation

CAN in Automation (CiA) is the international users’ and manufacturers’ group for the CAN
network (Controller Area Network), internationally standardized in the ISO 11898 series. The
nonprofit association was established in 1992. The aim is to provide an unbiased platform for
future developments of the CAN protocol and to promote the image of the CAN technology.

6.2 How to detect and identify CANopeen nodes

How to detect and identify CANopen nodes

So you’ve got a CAN bus with some devices, but you don’t know which of them speaks
“CANopen”, if any? The OVMS v3 will help you to detect them and open their CANs ;)

Before you begin


…you need to activate the CAN bus(es) you’re going to use. As a CANopen master needs to
write to the network, you need to start the interfaces in active mode, i.e. …:
OVMS# can can1 start active 500000

OVMS# can can2 start active 125000

… and then start the CANopen master for the bus(es), i.e.:
OVMS# copen can1 start

OVMS# copen can2 start

Detecting CANopen nodes

The “open” in “CANopen” means any implementation can decide how much of the standard it
implements. There are some few mandatory features though, a CANopen slave has to
implement, if it wants to comply with the standard.

The mandatory features helping to detect and identify CANopen nodes on a CAN bus are:

NMT (network management), especially RESET and PREOP

NMT bootup event messages

Standard SDO access in pre-operational mode

If you’ve got CANopen nodes on a bus, even silent ones, issuing  copen  …  nmt  reset  will tell
all of them to reboot, and as bootup messages are mandatory, you will see them in the OVMS
log output like this:
I (162904) canopen: can1 node 1 new state: Booting

The OVMS CANopen master continously monitors the network for NMT and EMCY messages.
After bootup of all nodes, you can get a list of all nodes that have been detected by
issuing  metrics  list  co. :

OVMS# metrics list co.

co.can1.nd1.emcy.code

co.can1.nd1.emcy.type

co.can1.nd1.state Operational

Note
if you request a reset, nodes may decide to boot into pre-operational state. That may
produce some error messages. Don’t worry, you can resolve this anytime by
issuing  copen  …  nmt  start .

Identifying CANopen nodes

In pre-operational state, a CANopen node must be accessible at the CANopen default IDs. That
means if the node supports SDO access, we can query some standard attributes from it.

That’s what  copen  …  info  and  copen  …  scan  do:


copen   …  info  queries the standard device attributes from a specific node,
copen   …  scan  queries all 127 node IDs.

Caution

There may be non-CANopen devices on the bus producing regular data frames at CANopen
response IDs and/or reading and possibly misinterpreting CANopen requests sent to node IDs
not planned by the manufacturer. Chances are low this triggers problems, but you should be
ready to switch off the vehicle when doing a scan – just in case.

A complete scan takes about 20 seconds. A typical scan could look like this:
OVMS# level debug canopen

OVMS# copen can1 scan

Scan #1-127...

Node #1:

Device type: 0x00000000

Error state: 0x00

Vendor ID: 0x0000001e

Product: 0x0712302d

Revision: 0x00010019

S/N: 0x47c5…………

Device name: Gen4 (Renault Twizy)11 November 2011 12

HW version: 0x00000003

SW version: 0712.0001

Node #23: SDO access failed

Node #25: SDO access failed

Node #27: SDO access failed

Node #30: SDO access failed

Node #87: SDO access failed

Done.
D (227994) canopen: ReadSDO #23 0x1000.00: InitUpload failed, CANopen error code
0xffffffff

D (228194) canopen: ReadSDO #25 0x1000.00: InitUpload failed, CANopen error code
0xffffffff

D (228444) canopen: ReadSDO #27 0x1000.00: InitUpload failed, CANopen error code
0xffffffff

D (228844) canopen: ReadSDO #30 0x1000.00: InitUpload failed, CANopen error code
0xffffffff

D (238384) canopen: ReadSDO #87 0x1000.00: InitUpload failed, CANopen error code
0xffffffff

This means one CANopen node was found, and some non-CANopen frames were received on
IDs 0x580 +23, +25, +27, +30 and +87.

6.3 CANopen Shell Commands

Show status report

copen status

Start / stop workers

copen <bus> start

copen <bus> stop

 stop will fail if clients are still running.

Send NMT commands

copen <bus> nmt <start|stop|preop|reset|commreset> [id=0] [timeout_ms=0]

id 0 = broadcast

timeout > 0: wait for state change (heartbeat), 3 tries Note: state change response is not
a mandatory CANopen feature.

Read SDO
copen <bus> readsdo <id> <index_hex> <subindex_hex> [timeout_ms=50]

index & subindex: hexadecimal without “0x” or “h”


defaults to 3 tries on timeout

Write SDO

copen <bus> writesdo <id> <index_hex> <subindex_hex> <value> [timeout_ms=50]

index & subindex: hexadecimal without “0x” or “h”

value: prefix “0x” = hex, else decimal, string if no decimal

defaults to 3 tries on timeout

Show node core attributes

copen <bus> info <id> [timeout_ms=50]

prints device type, error register, device name etc.

Note: some attributes read are optional and may be empty/zero.

Scan bus for nodes

copen <bus> scan [[startid=1][-][endid=127]] [timeout_ms=50]

loops “info” over multiple node ids (default: all)

Note: a full scan with default timeout takes ~20 seconds

6.4 CANopen API Usage

Synchronous API

The synchronous use is very simple, all you need is a  CANopenClient  instance.

On creation the client automatically connects to the active CANopen worker or


starts a new worker instance if necessary.

The  CANopenClient  methods will block until the job is done (or has failed). Job
results and/or error details are returned in the caller provided job.

Caution
Do not make synchronous calls from code that may run in a restricted context,
e.g. within a metric update handler. Avoid using synchronous calls from time
critical code, e.g. a CAN or event handler.
Example
#include "canopen.h"

// find CAN interface:

canbus* bus = (canbus*) MyPcpApp.FindDeviceByName("can1");

// …or simply use m_can1 if you're a vehicle subclass

// create CANopen client:

CANopenClient client(bus);

// a CANopen job holds request and response data:

CANopenJob job;

// read value from node #1 SDO 0x1008.00:

uint32_t value;

if (client.ReadSDO(&job, 1, 0x1008, 0x00, (uint8_t)&value, sizeof(value)) == COR_OK)


{

// read result is now in value

// start node #2, wait for presence:

if (client.SendNMT(&job, 2, CONC_Start, true) == COR_OK) {

// node #2 is now started

// write value into node #3 SDO 0x2345.18:

if (client.WriteSDO(&job, 3, 0x2345, 0x18, (uint8_t)&value, 0) == COR_OK) {

// value has now been written into register 0x2345.18

Main API methods


/**

* SendNMT: send NMT request and optionally wait for NMT state change

* a.k.a. heartbeat message.

* Note: NMT responses are not a part of the CANopen NMT protocol, and

* sending "heartbeat" NMT state updates is optional for CANopen nodes.

* If the node sends no state info, waiting for it will result in timeout

* even though the state has in fact changed -- there's no way to know

* if the node doesn't tell.

*/

CANopenResult_t SendNMT(CANopenJob& job,

uint8_t nodeid, CANopenNMTCommand_t command,

bool wait_for_state=false, int resp_timeout_ms=1000, int max_tries=3);

/**

* ReceiveHB: wait for next heartbeat message of a node,

* return state received.

* Use this to read the current state or synchronize to the heartbeat.

* Note: heartbeats are optional in CANopen.

*/

CANopenResult_t ReceiveHB(CANopenJob& job,

uint8_t nodeid, CANopenNMTState_t* statebuf=NULL,

int recv_timeout_ms=1000, int max_tries=1);

/**

* ReadSDO: read bytes from SDO server into buffer

* - reads data into buf (up to bufsize bytes)

* - returns data length read in job.sdo.xfersize

* - … and data length available in job.sdo.contsize (if known)

* - remaining buffer space will be zeroed

* - on result COR_ERR_BufferTooSmall, the buffer has been filled up to bufsize

* - on abort, the CANopen error code can be retrieved from job.sdo.error

* Note: result interpretation is up to caller (check device object dictionary

* for data types & sizes). As CANopen is little endian as ESP32, we don't
* need to check lengths on numerical results, i.e. anything from int8_t to

* uint32_t can simply be read into a uint32_t buffer.

*/

CANopenResult_t ReadSDO(CANopenJob& job,

uint8_t nodeid, uint16_t index, uint8_t subindex, uint8_t* buf, size_t bufsize,

int resp_timeout_ms=50, int max_tries=3);

/**

* WriteSDO: write bytes from buffer into SDO server

* - sends bufsize bytes from buf

* - … or 4 bytes from buf if bufsize is 0 (use for integer SDOs of unknown type)

* - returns data length sent in job.sdo.xfersize

* - on abort, the CANopen error code can be retrieved from job.sdo.error

* Note: the caller needs to know data type & size of the SDO register (check

* device object dictionary). As CANopen servers normally are intelligent,

* anything from int8_t to uint32_t can simply be sent as a uint32_t with

* bufsize=0, the server will know how to convert it.

*/

CANopenResult_t WriteSDO(CANopenJob& job,

uint8_t nodeid, uint16_t index, uint8_t subindex, uint8_t* buf, size_t bufsize,

int resp_timeout_ms=50, int max_tries=3);

If you want to create custom jobs, use the low level method  ExecuteJob()  to
execute them.

Asynchronous API

The  CANopenAsyncClient  class provides the asynchronous interface and the


response queue.

To use the asynchronous API you need to handle asynchronous responses,


which normally means adding a dedicated task for this. A minimal handling
would be to simply discard the responses (just empty the queue), if you don’t
need to care about the results.
Example

Instantiate the async client for a CAN bus and a queue size like this:

CANopenAsyncClient m_async(m_can1, 50);

Example response handler task:

void MyAsyncTask()

CANopenJob job;

while (true) {

if (m_async.ReceiveDone(job, portMAX_DELAY) != COR_ERR_QueueEmpty) {

// …process job results…

Sending requests is following the same scheme as with the synchronous API.
Standard result code is  COR_WAIT , an error may occur if the queue is full.

if (m_async.WriteSDO(m_nodeid, index, subindex, (uint8_t*)value, 0) != COR_WAIT) {

// …handle error…

Main API methods

The API methods are similar to the synchronous methods (see above).

CANopenResult_t SendNMT(uint8_t nodeid, CANopenNMTCommand_t command,

bool wait_for_state=false, int resp_timeout_ms=1000, int max_tries=3);

CANopenResult_t ReceiveHB(uint8_t nodeid, CANopenNMTState_t* statebuf=NULL,

int recv_timeout_ms=1000, int max_tries=1);


CANopenResult_t ReadSDO(uint8_t nodeid, uint16_t index, uint8_t subindex,

uint8_t* buf, size_t bufsize,

int resp_timeout_ms=100, int max_tries=3);

CANopenResult_t WriteSDO(uint8_t nodeid, uint16_t index, uint8_t subindex,

uint8_t* buf, size_t bufsize,

int resp_timeout_ms=100, int max_tries=3);

CANopenJob  objects are created automatically by these methods. Jobs done need
to be fetched by looping  ReceiveDone()  until it returns  COR_ERR_QueueEmpty .

If you want to create custom jobs, use the low level method  SubmitJob()  to add
them to the worker queue.

Error Handling

If an error occurs, it will be given as a  CANopenResult_t  other


than  COR_OK  or  COR_WAIT , either by a method result or by
the  CANopenJob.result  field.

Result codes are:

COR_OK = 0,

// API level:

COR_WAIT, // job waiting to be processed

COR_ERR_UnknownJobType,

COR_ERR_QueueFull,

COR_ERR_QueueEmpty,

COR_ERR_NoCANWrite,

COR_ERR_ParamRange,

COR_ERR_BufferTooSmall,

// Protocol level:

COR_ERR_Timeout,

COR_ERR_SDO_Access,
COR_ERR_SDO_SegMismatch,

// General purpose application level:

COR_ERR_DeviceOffline = 0x80,

COR_ERR_UnknownDevice,

COR_ERR_LoginFailed,

COR_ERR_StateChangeFailed

Additionally, if an SDO read/write error occurs, an abortion error code may be


given by the slave. These codes follow the CANopen standard and may be
extended by device specific codes.

To translate a  CANopenResult_t  and/or a known SDO abort code into a string, use
the  CANopen  class utility methods:

std::string GetAbortCodeName(const uint32_t abortcode);

std::string GetResultString(const CANopenResult_t result);

std::string GetResultString(const CANopenResult_t result, const uint32_t abortcode);

std::string GetResultString(const CANopenJob& job);

Example
if (job.result != COR_OK) {

ESP_LOGE(TAG, "Result for %s: %s",

CANopen::GetJobName(job).c_str(),

CANopen::GetResultString(job).c_str());

Custom Address Schemes

The standard clients use the CiA DS301 default IDs for node addressing, i.e.:

NMT request → 0x000

NMT response → 0x700 + nodeid

SDO request → 0x600 + nodeid


SDO response → 0x580 + nodeid

If you need another address scheme, create a sub class


of  CANopenAsyncClient  or  CANopenClient  and override the  Init…()  methods as
necessary.

More Code Examples

 See shell commands in  canopen_shell.cpp


 See classes  SevconClient  and  SevconJob  in the Twizy SEVCON module

7. dbc

DBC is a CAN data description file format introduced by Vector Informatik GmbH. DBC files are
text files so can be created and edited using a simple text editor like the one built into the
OVMS web UI.

DBC files can be used to support vehicles that don’t have a dedicated native adaption yet. This
is done using the generic DBC vehicle type, which can use DBC files to translate CAN data into
metrics.

This section tries to show you how to create and use a DBC specification on the OVMS. Of
course you’ll need to know how to decode your vehicle’s CAN frames first. You can use the
OVMS RE (reverse engineering) toolkit to identify which messages are on the bus and which
changes correlate to actions and status on the car.

There’s also a very good general introduction to DBC from CSS Electronics including an
explanatory video: https://www.csselectronics.com/screen/page/can-dbc-file-database-
intro/language/en

DBC files only specify the passive (reading) part, they don’t provide a means to define
transmissions. If you need to send frames to request certain information, you can still use the
OVMS DBC engine to decode the results (instead of doing the decoding in C++ code). So a DBC
file can be used as a base for a real vehicle module. To request OBD2 data during
development, you can use the  re  obdii  commands.

Basic Example

This example is taken from the Twizy, which sends some primary BMS status data at CAN ID
0x155 (341). Note: the Twizy module actually does not use DBC, this is just an example how
you would decode this message if using DBC.

Message example:  05  96  E7  54  6D  58  00  6F


Byte 0: charge current limit [A], scaled by 5, no offset:  05  → 25A

Bytes 1+2: momentary battery current [A], big endian, lower 12 bits, scaled by -0.25, offset
+500:  _6  E7  → 58.25A

Bytes 4+5: SOC [%], big endian, scaled by 0.0025, no offset:  6D  58  → 69.98%

These can be translated to metrics directly:

Charge current limit:  v.c.climit

Momentary battery current:  v.b.current

Battery SOC:  v.b.soc

Create DBC File

Copy & paste the following into a new editor window:


VERSION "DBC Example 1.0"

BS_: 500000 : 0,0

BO_ 341 BMS_1: 8 Vector__XXX

SG_ v_c_climit : 7|8@0+ (5,0) [0|35] "A" Vector__XXX

SG_ v_b_current : 11|12@0+ (-0.25,500) [-500|1000] "A" Vector__XXX

SG_ v_b_soc : 39|16@0+ (0.0025,0) [0|100] "%" Vector__XXX

What does this mean?

BS_  defines the bus speed (500 kbit in this example) and bit timings (unused)

BO_  defines the data object, a CAN frame of length 8 with ID 341 (0x155) (“BMS_1” is just an
arbitrary name)

SG_  lines define the signals (values) embedded in the object (see below)

Vector__XXX  is just a placeholder for any sender/receiver (currently unused by the OVMS)

Signals are defined by their…

Name (= metric name with  .  replaced by  _ )

Start position (bit position) and bit length ( 7|8 )

Endianness:  0  = big endian (most significant byte first),  1  = little endian (least significant byte
first) (Note: the DBC format documentation is wrong on this)
Signedness:  +  = unsigned,  -  = signed

Scaling and offset:  (-0.25,500)  => real value = raw value * -0.25 + 500

Minimum/maximum:  [-500|1000]  = valid real values are in the range -500 to 1000

Unit: e.g.  "A"  (ignored/irrelevant, defined by the metric)

The metric to set can be given as the name of the signal. You may use the metric name directly
on the OVMS, but to conform to the DBC standard, replace the dots by  _ .

Bit positions are counted from byte 0 upwards by their significance, regardless of the
endianness. The first message byte has bits 0…7 with bit 7 being the most significant bit of the
byte. The second byte has bits 8…15 with bit 15 being the MSB, and so on:
[ 7 6 5 4 3 2 1 0 ] [ 15 14 13 12 11 10 9 8 ] [ 23 22 21 20 …

`----- Byte 0 ----´ `------- Byte 1 --------´ `----- Byte 2 …

For big endian values, signal start bit positions are given for the most significant bit. For little
endian values, the start position is that of the least significant bit.

Use DBC File

Save the DBC example as:  /store/dbc/twizy1.dbc  (the directory will be created by the editor)

Open the shell. To see debug logs, issue  log  level  debug  dbc-
parser  and  log  level  debug  v-dbc .

Note: the DBC parser currently isn’t graceful on errors, a wrong DBC file may crash the
module. So you should only enable automatic loading of DBC files on boot when you’re done
developing and testing it.

So let’s first try if the DBC engine can parse our file. The  dbc  autoload  command loads all
DBC files from the  /store/dbc  directory:

OVMS# dbc autoload

Auto-loading DBC files...

D (238062) dbc-parser: VERSION parsed as: DBC Example 1.0

D (238062) dbc-parser: BU_ parsed 1 nodes

D (238062) dbc-parser: BO_ parsed message 341

D (238072) dbc-parser: SG_ parsed signal v_c_climit

D (238072) dbc-parser: SG_ parsed signal v_b_current

D (238082) dbc-parser: SG_ parsed signal v_b_soc

Looks good.  dbc  list  can tell us some statistics:

OVMS# dbc list


twizy1: DBC Example 1.0: 1 message(s), 3 signal(s), 56% coverage, 1 lock(s)

The coverage tells us how much of our CAN data bits are covered by signal definitions.

Now let’s load the file into the DBC vehicle:


OVMS# config set vehicle dbc.can1 twizy1

Parameter has been set.

OVMS# vehicle module NONE

I (1459922) v-none: Generic NONE vehicle module

OVMS# vehicle module DBC

I (249022) v-dbc: Pure DBC vehicle module

I (249022) v-dbc: Registering can bus #1 as DBC twizy1

Nice. Let’s simulate receiving our test frame and check the decoded metrics:
OVMS# can can1 rx standard 155 05 96 E7 54 6D 58 00 6F

OVMS# me li v.b.soc

v.b.soc 69.98%

OVMS# me li v.b.current

v.b.current 58.25A

OVMS# me li v.c.climit

v.c.climit 25A

So the decoding apparently works.

To configure DBC mode for autostart we now just need to set the DBC vehicle mode to be
loaded on vehicle startup, and to enable autoloading of the DBC files from  /store/dbc . You
can do so either by using the user interface page Config → Autostart (check “Autoload DBC
files” and set the vehicle type to “DBC”), or from the shell by…
OVMS# config set auto dbc yes

OVMS# config set auto vehicle.type DBC

Try a reboot to see if everything works.


You can now add more objects and signals to your DBC file.

8. disable

9. egpio
Hardware

The OVMS has 10 general purpose I/O ports, provided by a MAX7317 I/O expander.

The MAX7317 ports can be individually configured as either an open-drain output, or an


overvoltage-protected Schmitt input. Being open-drain, you need to add pull-up resistors for
input and output switch uses to get a defined high level (e.g. 10K to 3.3V). See the datasheet
for details on maximum current & voltage ratings.

Depending on your hardware configuration, up to 4 ports may be used by the module. 6 are
generally free to use.

Por Signal(s) Exp.Pin Default usage


t
0 MDM_EN 15 Modem enable
1 SW_CTL – Ext12V control (SW_12V)
2 CAN1_EN + EIO_1 17 CAN1 transceiver enable
3 MDM_DTR + EIO_2 19 Modem sleep control
4 EIO_3 21 -free-
5 EIO_4 20 -free-
6 EIO_5 18 -free-
7 EIO_6 16 -free-
8 EIO_7 14 -free-
9 EIO_8 12 -free-

SW_CTL  (port 1) controls a BTS452R power switch, which could deliver a nominal output of


25W or 1.8A, and up to 40W or 2.9A short term at the  SW_12V  pin, but the main fuse of the
module (located at the corner near the DB9 plug) limits the 12V current total sum of the board
plus any external hardware to continuous 0.75A on a revision 3.1 board and 1.0A on a revision
3.2 board. The unswitched  EXT_12V  pin is also behind the fuse.

The module including modem needs a 12V current share of ~80mA in full operation. Calculate
with 100mA to be on the safe side. That leaves continuous 0.65A on a revision 3.1 board
and 0.9A on a revision 3.2 board for external devices and addons powered by the module. The
fuse has a little headroom, but don’t rely on that.

SW_12V  is meant to power auxiliary devices from the OVMS, for example head-up displays. Of
course you can as well power a standard 12V automotive relay or fan directly from this
without additional hardware.
The EGPIO (EIO) ports are not connected directly to the DA26 connector but are available at
the internal expansion port. To route an EGPIO port to the DA26 connector, connect it to one
of the  GEP_1…7  lines at the expansion port, either directly or via some additional driver.

Example: to route EIO_8 (port 9) to GEP_7 (pin 21 on the DA26), set a jumper on pins 10+12 on
the expansion port.

Commands
EGPIO control is provided by the egpio command set:

 egpio  output  <port>  <level>  [<port>  <level>  …]  – set output level(s)


 egpio  input  <port>  [<port>  …]  – query input level(s)
 egpio  status  – show output, input & monitor status
 egpio  monitor  <on|off>  [ports]  – enable/disable monitoring
 egpio  monitor  status  – show current monitoring status

To configure a port for input, it needs to be switched to output level high (1). That is done
automatically by the  input  and  monitor  commands.

If you set multiple outputs, the ports will be set one at a time, so output levels will change with
a slight delay. You can use this behaviour to set data lines before a clock line, e.g. when
sending bits serially into a shift register.

Configuration

Paramete Instance Description


r
auto egpio yes = Start monitoring on boot (default: no)
egpio monitor.ports List of ports to monitor by default (space separated)
egpio monitor.interva Polling interval in milliseconds (min 10, default 50)
l

The default interval of 50 ms (= 20 Hz) means an input signal needs to be at least 50 ms long to
be detected. This polling frequency produces a CPU load of ~0.5% on core 1 and is normally
sufficient to detect even very short button pushes.

Metrics

Metric name Example value Description


m.egpio.input 0,1,2,3,4,5,6,7, EGPIO input port state (ports 0…9, present=high)
9
m.egpio.monitor 8,9 EGPIO input monitoring ports
m.egpio.output 4,5,6,7,9 EGPIO output port state

Hint: to process these metrics from Javascript, read them into an array using  eval()  and test
for the presence of a port number using e.g. the  includes()  method in a browser plugin.
Duktape does not support  includes() , you can test  indexOf(port)  instead.

Example:
var input = eval(OvmsMetrics.AsJSON("m.egpio.input"));

if (input.indexOf(9) < 0)

print("Input port 9 (EIO8) is currently low\n");

Events

Event Data Purpose


egpio.input.<port>.<state> – EGPIO input port change (port=0…9, state=high/low)
egpio.output.<port>.<state – EGPIO output port change (port=0…9, state=high/low)
>

Hint: to listen to events from Javascript, bind to  msg:event  on a  .receiver  object from
browser context or use  PubSub  from module context.

Example:
PubSub.subscribe("egpio.input.9.low", function(){

print("Input port 9 (EIO8) is now low\n");

});
10. enable

11. event

Internally, OVMS raises events whenever significant events occur. An event is a lightweight
message of a name plus optionally associated internal binary data. Event names are top-down
structured (so can be filtered by prefix) and sufficient to identify the source and type of the
event. Individual vehicle types may also issue their own events, and custom user events are
also possible.

To bind a script to an event, save the script in directory /store/events/<eventname> (hint:


directories can be created using the web UI editor). Whenever events are triggered, all the
scripts in the corresponding /store/events/<eventname> directory are executed. Event scripts
are executed in alphanumerical order of their names. Good practice is to prefix script names
with 2-3 digit numbers in steps of 10 or 100 (i.e. first script named 50-…), so new scripts can
easily be integrated at a specific place. If the event script is written in Javascript, be sure to add
the suffix .js to the name. Other names will be executed using the standard command
interpreter.

If you want to introduce a custom event (e.g. for a plugin), prefix the event name
by usr.<pluginname>. followed by the event purpose. Example: Foglight

Be aware events are processed in series from a queue, so depending on the system load and
the list of registered event listeners, there may be some delay from event generation to e.g. a
script execution

11.1 Commands

event   list  [<key>]  – Show registered listeners for all or events matching a key (part of the
name)

event   trace  <on|off>  – Enable/disable logging of events at the “info” level. Without
tracing, events are also logged, but at the “debug” level. Ticker events are never logged.

event   raise  [-d<delay_ms>]  <event>  – Manually raise an event, optionally with a delay.
You can raise any event you like, but you shouldn’t raise system events without good
knowledge of their effects.

11.2 Standard Events

Event Data Purpose

app.connected One or more remote Apps have


connected
app.disconnected No remote Apps are currently
connected

canopen.node.emcy <event> CANopen node emergency


received

canopen.node.state <event> CANopen node state change


received

canopen.worker.start <worker> CANopen bus worker task started

canopen.worker.stop <worker> CANopen bus worker task


stopping

clock.HHMM Per-minute local time, hour HH,


minute MM

clock.dayN Per-day local time, day N (0=Sun,


6=Sat)

config.changed Configuration has changed

config.mounted Configuration is mounted and


available

config.unmounted Configuration is unmounted and


unavailable

egpio.input.<port>.<state> EGPIO input port change


(port=0…9, state=high/low)

egpio.output.<port>.<state> EGPIO output port change


(port=0…9, state=high/low)

gps.lock.acquired GPS lock has been acquired

gps.lock.lost GPS lock has been lost

housekeeping.init Housekeeping has initialised

location.alert.flatbed.moved GPS movement of parked vehicle


detected

location.enter.<name> <name> The specified geolocation has


been entered
location.leave.<name> <name> The specified geolcation has been
left

network.down All networks are down

network.interface.change Network interface change


detected

network.interface.up Network connection is


established

network.mgr.init Network manager has initialised

network.mgr.stop Network managed has been


stopped

network.modem.down Modem network is down

network.modem.up Modem network is up

network.reconfigured Networking has been


reconfigured

network.up One or more networks are up

network.wifi.down WIFI network is down

network.wifi.sta.bad WIFI client has bad signal level

network.wifi.sta.good WIFI client has good signal level

network.wifi.up WIFI network is up

retools.cleared.all RE frame log has been cleared

retools.cleared.changed RE frame change flags cleared

retools.cleared.discovered RE frame discovery flags cleared


retools.mode.analyse RE switched to analysis mode

retools.mode.discover RE switched to discovery mode

retools.started RE (reverse engineering) toolkit


started

retools.stopped RE toolkit stopped

retools.pidscan.start RE OBD2 PID scan started

retools.pidscan.stop RE OBD2 PID scan stopped

retools.pidscan.done RE OBD2 PID scan completed

sd.insert The SD card has just been


inserted

sd.mounted The SD card is mounted and ready


to use

sd.remove The SD card has just been


removed

sd.unmounted The SD card has completed


unmounting

sd.unmounting The SD card is currently


unmounting

server.v2.authenticating V2 server connection is


authenticating

server.v2.connected V2 server connection established


online

server.v2.connecting V2 server connection in progress

server.v2.connectwait V2 server is pausing before


connection

server.v2.disconnected V2 server connection has been


lost
server.v2.stopped V2 server has been stopped

server.v2.waitnetwork V2 server connection is waiting


for network

server.v2.waitreconnect V2 server is pausing before re-


connection

server.v3.authenticating V3 server connection is


authenticating

server.v3.connected V3 server connection established


online

server.v3.connecting V3 server connection in progress

server.v3.connectwait V3 server is pausing before


connection

server.v3.disconnected V3 server connection has been


lost

server.v3.stopped V3 server has been stopped

server.v3.waitnetwork V3 server connection is waiting


for network

server.v3.waitreconnect V3 server is pausing before re-


connection

server.web.socket.closed <cnt> Web server lost a websocket


client

server.web.socket.opened <cnt> Web server has a new websocket


client

system.modem.down Modem has been disconnected

system.modem.gotgps Modem GPS has obtained lock

system.modem.gotip Modem received IP address from


DATA

system.modem.lostgps Modem GPS has lost lock


system.modem.muxstart Modem MUX has started

system.modem.netdeepsleep Modem is deep sleeping DATA


network

system.modem.nethold Modem is pausing DATA network

system.modem.netloss Modem has lost DATA network

system.modem.netsleep Modem is sleeping DATA network

system.modem.netstart Modem is starting DATA network

system.modem.netwait Modem is pausing before starting


DATA

system.modem.poweredon Modem is powered on

system.modem.poweringon Modem is powering on

system.modem.received.ussd <ussd> A USSD message has been


received

system.modem.stop Modem has been shut down

system.shutdown System has been shut down

system.shuttingdown System is shutting down

system.start System is starting

system.vfs.file.changed <path> VFS file updated (note: only sent


on some file changes)

system.wifi.ap.sta.connected WiFi access point got a new client


connection

system.wifi.ap.sta.disconnected WiFi access point lost a client


connection
system.wifi.ap.sta.ipassigned WiFi access point assigned an IP
address to a client

system.wifi.ap.start WiFi access point mode starting

system.wifi.ap.stop WiFi access point mode stopping

system.wifi.down WiFi is shutting down

system.wifi.scan.done WiFi scan has been finished

system.wifi.sta.connected WiFi client is connected to a


station

system.wifi.sta.disconnected WiFi client has disconnected from


a station

system.wifi.sta.gotip WiFi client got an IP address

system.wifi.sta.lostip WiFi client lost it’s IP address

system.wifi.sta.start WiFi client mode starting

ticker.1 One second has passed since last


ticker

ticker.10 Ten seconds have passed

ticker.300 Five minutes have passed

ticker.3600 One hour has passed

ticker.60 One minute has passed

ticker.600 Ten minutes have passed

vehicle.alarm.off Vehicle alarm has been disarmed


vehicle.alarm.on Vehicle alarm has been armed

vehicle.alert.12v.off 12V system voltage has recovered

vehicle.alert.12v.on 12V system voltage is below alert


threshold

vehicle.alert.bms BMS cell/pack volts/temps


exceeded thresholds

vehicle.asleep Vehicle systems are asleep

vehicle.awake Vehicle systems are awake

vehicle.aux.12v.on Vehicle 12V auxiliary system is on


(base system awake)

vehicle.aux.12v.off Vehicle 12V auxiliary system is off

vehicle.charge.12v.start Vehicle 12V battery is charging

vehicle.charge.12v.stop Vehicle 12V battery has stopped


charging

vehicle.charge.finished Vehicle charge has completed


normally

vehicle.charge.mode <mode> Vehicle charge mode has been set

vehicle.charge.pilot.off Vehicle charge pilot signal is off

vehicle.charge.pilot.on Vehicle charge pilot signal is on

vehicle.charge.prepare Vehicle is preparing to charge

vehicle.charge.start Vehicle has started to charge

vehicle.charge.state <state> Vehicle charge state has changed


vehicle.charge.stop Vehicle has stopped charging

vehicle.charge.timermode.off Vehicle charge timer mode has


been switched off

vehicle.charge.timermode.on Vehicle charge timer mode has


been switched on

vehicle.drivemode.<n> Vehicle drivemode has been set


to profile <n> (vehicle specific)

vehicle.gear.forward Vehicle has been put in forward


gear

vehicle.gear.neutral Vehicle has been put in neutral


gear

vehicle.gear.reverse Vehicle has been put in reverse


gear

vehicle.headlights.off Vehicle headlights are off

vehicle.headlights.on Vehicle headlights are on

vehicle.locked Vehicle has been locked

vehicle.off Vehicle has been switched off

vehicle.on Vehicle has been switched on

vehicle.require.gps A vehicle has indicated it requires


GPS

vehicle.require.gpstime A vehicle has indicated it requires


GPS time

vehicle.type.cleared Vehicle module has been


unloaded

vehicle.type.set <type> Vehicle module has been loaded

vehicle.unlocked Vehicle has been unlocked


vehicle.valet.off Vehicle valet mode deactivated

vehicle.valet.on Vehicle valet mode activated

12. exit

13. help

14. homelink

15. location

16. lock

17. log
Logging to the Console

Components of the OVMS system output diagnostic logs (information, warnings, etc). You can
choose to display these logs on your connected console with the ‘log monitor yes/no’
command:

OVMS# log monitor ?


Usage: log monitor [no|yes]
no Don't monitor log
yes Monitor log

By default, the USB console will have log monitoring ‘yes’, SSH (and telnet if enabled) ‘no’.

The web shell does not use the log monitor command but has a checkbox in the upper right
corner of the shell panel instead. The keyboard shortcut for the checkbox is L (Alt-L or Alt-Shift-
L depending on your browser). The web frontend gets the continuous stream of log messages
independent of the shell panel or the monitoring being active, and shows the last 100
messages received when opening the shell panel.

Logs are output at various levels of verbosity, and you can control what is shown both globally
and on a per-component basis:
OVMS# log level ?

none No logging (0)

error Log at the ERROR level (1)

warn Log at the WARN level (2)

info Log at the INFO level (3)

debug Log at the DEBUG level (4)

verbose Log at the VERBOSE level (5)

(Note: sorted here for level clarity)

The syntax of this command is log level <level> [<component>]. If the component is not


specified, the level applies to all components that don’t get a level set explicitly afterwards.
The levels increase in verbosity, and setting a particular level will also include all log output at a
lower level of verbosity (so, for example, setting level info will also
include warn and error output).

A log line typically looks like this:

I (32244049) ovms-server-v2: One or more peers have connected

│ │ │ └─ Log message

│ │ └─ Component name

│ └─ Timestamp (milliseconds since boot)

└─ Log level (I=INFO)

Log levels are applied on log message generation, so a later change to a higher level will not
reveal messages generated previously.

Logging to SD CARD

You can also choose to store logs on SD CARD. This is very useful to capture debugging
information for the developers, as the log will show what happened before a crash or
misbehaviour.

We recommend creating a directory to store logs, i.e.:

OVMS# vfs mkdir /sd/logs


To enable logging to a file, issue for example:

OVMS# log file /sd/logs/20180420.log

The destination file can be changed any time. To disable logging to the file, issue  log close ,
to restart logging after a close issue  log open . You may choose an arbitrary file name, good
practice is using some date and/or bug identification tag. Note: logging will append to the file if
it already exists. To remove a file, use  vfs rm ….

File logging does not persist over a reboot or crash (unless configured as shown below), you
can use a script bound to the  sd.mounted  event to re-enable file logging automatically or
configure automatic logging (see below).

You can use the webserver to view and download the files. The webserver default
configuration enables directory listings and access to files located under the document root
directory, which is /sd by default. Any path not bound to an internal webserver function is
served from the document root. So you can get an inventory of your log files now at the URL:

http://192.168.4.1/logs/X

…and access your log files from there or directly by their respective URLs. Another option to
retrieve the files without unmounting the SD card is by scp if you have configured SSH access.

Logging Configuration

Use the web UI or config command to configure your log levels and file setup to be applied
automatically on boot:

OVMS# config list log

log (readable writeable)

file.enable: yes

file.keepdays: 7

file.maxsize: 1024
file.path: /sd/logs/log

file.syncperiod: 3

level: info

level.simcom: info

level.v-twizy: verbose

level.webserver: debug

The  log  command can be used for temporary changes, if you change the configuration, it will
be applied as a whole, replacing your temporary setup.

If a maximum file size >0 is configured, the file will be closed and archived when the size is
reached. The archive name consists of the log file name with added suffix of the timestamp,
i.e.  /sd/logs/log.20180421-140356 . Using a logs directory will keep all your archived logs
accessible at one place. If  file.keepdays  is defined, older archived logs will automatically be
deleted on a daily base.
Take care not to remove an SD card while logging to it is active (or any running file access). The
log file should still be consistent, as it is synchronized after every write, but the SD file system
currently cannot cope with SD removal with open files. You will need to reboot the module. To
avoid this, always use the “Close” button or the  log close  command before removing the SD
card.

You don’t need to re-enable logging to an SD path after insertion, the module will watch for
the mount event and automatically start logging to it.

Performance Impact

SD card I/O has an impact on the module performance. So file logging should generally be
switched off or run on a low level (i.e. “info” or “warn”) unless you’re hunting some bug or
checking some details of operation. We also recommend using a fast SD card for logging (check
the speed with  sd status , check if you can raise config  sdcard maxfreq.khz  to 20000 kHz).

File logging is done by a separate task, but flushing the file buffers to the SD card still may
block the logging CPU core or even both CPU cores for a short period. To reduce the impact of
this, the log task by default only flushes the buffer after 1.5 seconds of log inactivity. This
means you may lose the last log messages before a crash.

To change the flush behaviour, set config  file.syncperiod  to…

 0 = never flush (i.e. only at  log close  / log cycle)


 < 0 = flush every n log messages (i.e. -1 = flush after every message)
 > 0 = flush after n/2 seconds idle

The log task counts the time spent for flushes and outputs it with the  log status  command:

OVMS# log status

Log listeners : 3

File logging status: active

Log file path : /sd/logs/log

Current size : 817.0 kB

Cycle size : 1024 kB

Cycle count : 8

Dropped messages : 0
Messages logged : 70721

Total fsync time : 651.1 s

This is an example for the default configuration of file.syncperiod: 3, the logging here has on
average taken 651.1 / 70721 = 9 ms per message.

18. Metrics
Metrics are at the heart of the OVMS v3 system. They are strongly typed named parameters,
with values in specific units (and able to be automatically converted to other units). For
example, a metric to record the motor temperature may be an integer in Celsius units, and
may be convertible to Fahrenheit.

The full list of metrics available can be shown:

OVMS# metrics list


m.freeram 4232852
m.hardware OVMS WIFI BLE BT cores=2 rev=ESP32/1
m.monotonic 3568Sec
...
v.p.latitude 22.2809
v.p.longitude 114.161
v.p.odometer 100000Km
v.p.satcount 12
v.p.speed 0Kph
v.p.trip 0Km
v.t.alert 0,0,0,1
v.t.health 95,93,96,74%
v.t.pressure 206.843,216.483,275.79,175.79kPa
v.t.temp 33,33,34,38°C
v.type DEMO

You can filter the  metrics list  output for names matching a given substring, for
example  metrics list volt  will show all voltage related metrics.
A base OVMS v3 system has more than 100 metrics available (see below), and vehicle modules
can add more for their own uses (see vehicle sections).

In general, vehicle modules (and some other system components) are responsible for updating
the metrics, and server connections read those metrics, reformat them, and send them on to
servers and Apps (for eventual display to the user). Status commands (such as STAT) also read
these metrics and display them in user-friendly forms:

OVMS# stat
Not charging
SOC: 50.0%
Ideal range: 200Km
Est. range: 160Km
ODO: 100000.0Km
CAC: 160.0Ah
SOH: 100%

For developer use, there are also some other metric commands used to manually modify a
metric’s value (for testing and simulation purposes), and trace changes:

OVMS# metrics ?
list Show all metrics
persist Show persistent metrics info
set Set the value of a metric
trace METRIC trace framework

Some metrics are presistent across warm reboots. This prevents values such as SOC from being
lost when firmware is updated (or in the event of a crash). You can display these
with  metrics list -p  and view general information about presistent metrics
with  metrics persist.

Metric name Example Value Description

m.freeram 3275588 Total amount of free RAM in bytes

m.hardware OVMS WIFI BLE BT… Base module hardware info

m.monotonic 49607Sec Uptime in seconds

m.net.mdm.iccid 8,94902E+19 SIM ICCID


m.net.mdm.model 35316B09SIM5360E Modem module hardware info

m.net.mdm.network congstar Current GSM network provider

m.net.mdm.sq -101dBm …and signal quality

m.net.provider WLAN-214677 Current primary network provider

m.net.sq -79dBm …signal quality

m.net.type wifi …and type (none/modem/wifi)

m.net.wifi.network WLAN-214677 Current Wifi network SSID

m.net.wifi.sq -79.1dBm …and signal quality

m.serial Reserved for module serial no.

m.tasks 20 Task count (use module tasks to list)

m.time.utc 1572590910Sec UTC time in seconds

m.version 3.2.005-155- Firmware version


g3133466f/…

m.egpio.input 0,1,2,3,4,5,6,7,9 EGPIO input port state (ports 0…9,


present=high)

m.egpio.monitor 8,9 EGPIO input monitoring ports

m.egpio.output 4,5,6,7,9 EGPIO output port state

s.v2.connected yes yes = V2 (MP) server connected

s.v2.peers 1 V2 clients connected


s.v3.connected yes = V3 (MQTT) server connected

s.v3.peers V3 clients connected

v.b.12v.current 0A Auxiliary 12V battery momentary current

v.b.12v.voltage 12.29V Auxiliary 12V battery momentary voltage

v.b.12v.voltage.alert yes = auxiliary battery under voltage alert

v.b.12v.voltage.ref 12.3V Auxiliary 12V battery reference voltage

v.b.c.temp 13,13,…,13°C Cell temperatures

v.b.c.temp.alert 0,0,…,0 Cell temperature deviation alert level


[0=normal, 1=warning, 2=alert]

v.b.c.temp.dev.max 1.43,0.86,…,-1.29°C Cell maximum temperature deviation


observed

v.b.c.temp.max 19,18,…,17°C Cell maximum temperatures

v.b.c.temp.min 13,12,…,12°C Cell minimum temperatures

v.b.c.voltage 4.105,4.095, Cell voltages


…,4.105V

v.b.c.voltage.alert 0,0,…,0 Cell voltage deviation alert level


[0=normal, 1=warning, 2=alert]

v.b.c.voltage.dev.max 0.0096,-0.0104, Cell maximum voltage deviation observed


…,0.0125V

v.b.c.voltage.max 4.135,4.125,…,4.14V Cell maximum voltages

v.b.c.voltage.min 3.875,3.865,…,3.88V Cell minimum voltages

v.b.cac 90.7796Ah Calculated battery pack capacity


v.b.consumption 0Wh/km Main battery momentary consumption

v.b.coulomb.recd 47.5386Ah Main battery coulomb recovered on


trip/charge

v.b.coulomb.recd.total 947.5386Ah Main battery coulomb recovered total


(life time)

v.b.coulomb.used 0.406013Ah Main battery coulomb used on trip

v.b.coulomb.used.total 835.406013Ah Main battery coulomb used total (life


time)

v.b.current 0A Main battery momentary current


(output=positive)

v.b.energy.recd 2.69691kWh Main battery energy recovered on


trip/charge

v.b.energy.recd.total 3212.69691kWh Main battery energy recovered total (life


time)

v.b.energy.used 0.0209496kWh Main battery energy used on trip

v.b.energy.used.total 3177.0209496kWh Main battery energy used total (life time)

v.b.health General textual description of battery


health

v.b.p.level.avg 95897% Cell level - pack average

v.b.p.level.max 96.41% Cell level - strongest cell in pack

v.b.p.level.min 94871% Cell level - weakest cell in pack

v.b.p.level.stddev 0.548% Cell level - pack standard deviation

v.b.p.temp.avg 13°C Cell temperature - pack average

v.b.p.temp.max 13°C Cell temperature - warmest cell in pack


v.b.p.temp.min 13°C Cell temperature - coldest cell in pack

v.b.p.temp.stddev 0°C Cell temperature - current standard


deviation

v.b.p.temp.stddev.max 0.73°C Cell temperature - maximum standard


deviation observed

v.b.p.voltage.avg 4.1V Cell voltage - pack average

v.b.p.voltage.grad 0.0032V Cell voltage - gradient of current series

v.b.p.voltage.max 4.105V Cell voltage - strongest cell in pack

v.b.p.voltage.min 4.09V Cell voltage - weakest cell in pack

v.b.p.voltage.stddev 0.00535V Cell voltage - current standard deviation

v.b.p.voltage.stddev.m 0.00783V Cell voltage - maximum standard


ax deviation observed

v.b.power 0kW Main battery momentary power


(output=positive)

v.b.range.est 99km Estimated range

v.b.range.full 50.8km Ideal range at 100% SOC & current


conditions

v.b.range.ideal 48km Ideal range

v.b.range.speed 21.6km/h Momentary ideal range gain/loss


(charge/discharge) speed

v.b.soc 96.3% State of charge

v.b.soh 85% State of health

v.b.temp 13°C Main battery momentary temperature


v.b.voltage 57.4V Main battery momentary voltage

v.c.12v.current 7.8A Output current of DC/DC-converter

v.c.12v.power 123W Output power of DC/DC-converter

v.c.12v.temp 34.5°C Temperature of DC/DC-converter

v.c.12v.voltage 12.3V Output voltage of DC/DC-converter

v.c.charging no yes = currently charging

v.c.climit 0A Maximum charger output current

v.c.current 1.25A Momentary charger output current

v.c.duration.full 25Min Estimated time remaing for full charge

v.c.duration.range -1Min … for sufficient range

v.c.duration.soc 0Min … for sufficient SOC

v.c.efficiency 87.6% Momentary charger efficiency

v.c.kwh 2.6969kWh Energy sum for running charge

v.c.kwh.grid 3.6969kWh Energy drawn from grid during running


session

v.c.kwh.grid.total 256.69kWh Energy drawn from grid total (life time)

v.c.limit.range 0km Sufficient range limit for current charge

v.c.limit.soc 80% Sufficient SOC limit for current charge


v.c.mode standard standard, range, performance, storage

v.c.pilot no Pilot signal present

v.c.power 125kW Momentary charger input power

v.c.state done charging, topoff, done, prepare,


timerwait, heating, stopped

v.c.substate scheduledstop, scheduledstart,


onrequest, timerwait, powerwait,
stopped, interrupted
v.c.temp 16°C Charger temperature

v.c.time 0Sec Duration of running charge

v.c.timermode yes = timer enabled

v.c.timerstart Time timer is due to start, seconds since


midnight UTC

v.c.type undefined, type1, type2, chademo,


roadster, teslaus, supercharger, ccs

v.c.voltage 0V Momentary charger supply voltage

v.d.cp yes yes = Charge port open

v.d.fl yes = Front left door open

v.d.fr yes = Front right door open

v.d.hood yes = Hood/frunk open

v.d.rl yes = Rear left door open

v.d.rr yes = Rear right door open


v.d.trunk yes = Trunk open

v.e.alarm yes = Alarm currently sounding

v.e.aux12v yes = 12V auxiliary system is on (base


system awake)

v.e.awake no yes = Vehicle is fully awake (switched on


by the user)

v.e.c.config yes = ECU/controller in configuration


state

v.e.c.login yes = Module logged in at ECU/controller

v.e.cabintemp 20°C Cabin temperature

v.e.cabinfan 100% Cabin fan

v.e.cabinsetpoint 24°C Cabin set point

v.e.cabinintake fresh Cabin intake type (fresh, recirc, etc)

v.e.cabinvent feet,face Cabin vent type (comma-separated list of


feet, face, screen, etc)

v.e.charging12v no yes = 12V battery is charging

v.e.cooling yes = Cooling

v.e.drivemode 33882626 Active drive profile code (vehicle specific)

v.e.drivetime 0Sec Seconds driving (turned on)

v.e.footbrake 0% Brake pedal state [%]

v.e.gear Gear/direction; negative=reverse,


0=neutral
v.e.handbrake yes = Handbrake engaged

v.e.headlights yes = Headlights on

v.e.heating yes = Heating

v.e.hvac yes = HVAC active

v.e.locked yes = Vehicle locked

v.e.on no yes = Vehicle is in “ignition” state


(drivable)

v.e.parktime 49608Sec Seconds parking (turned off)

v.e.regenbrake yes = Regenerative braking active

v.e.serv.range 12345km Distance to next scheduled


maintenance/service [km]

v.e.serv.time 1572590910Sec Time of next scheduled


maintenance/service [Seconds]

v.e.temp Ambient temperature

v.e.throttle 0% Drive pedal state [%]

v.e.valet yes = Valet mode engaged

v.g.generating no True = currently delivering power

v.g.climit 0A Maximum generator input current (from


battery)

v.g.current 1.25A Momentary generator input current


(from battery)

v.g.duration.empty 25Min Estimated time remaining for full


discharge
v.g.duration.range -1Min … for range limit

v.g.duration.soc 0Min … for SOC limit

v.g.efficiency 87.6% Momentary generator efficiency

v.g.kwh 2.6969kWh Energy sum generated in the running


session

v.g.kwh.grid 3.6969kWh Energy sent to grid during running session

v.g.kwh.grid.total 256.69kWh Energy sent to grid total

v.g.limit.range 0km Minimum range limit for generator mode

v.g.limit.soc 80% Minimum SOC limit for generator mode

v.g.mode standard Generator mode (TBD)

v.g.pilot no Pilot signal present

v.g.power 125kW Momentary generator output power

v.g.state done Generator state (TBD)

v.g.substate Generator substate (TBD)

v.g.temp 16°C Generator temperature

v.g.time 0Sec Duration of generator running

v.g.timermode false True if generator timer enabled

v.g.timerstart Time generator is due to start


v.g.type Connection type (chademo, ccs, …)

v.g.voltage 0V Momentary generator output voltage

v.i.temp Inverter temperature

v.i.power 42.7kW Momentary inverter motor power


(output=positive)

v.i.efficiency 98.2% Momentary inverter efficiency

v.m.rpm Motor speed (RPM)

v.m.temp 0°C Motor temperature

v.p.acceleration 0m/s² Vehicle acceleration

v.p.altitude 327.8m GPS altitude

v.p.direction 31.2° GPS direction

v.p.gpshdop 1.3 GPS horizontal dilution of precision


(smaller=better)

v.p.gpslock no yes = has GPS satellite lock

v.p.gpsmode AA <GPS><GLONASS>; N/A/D/E


(None/Autonomous/Differential/Estimate
d)
v.p.gpsspeed 0km/h GPS speed over ground

v.p.latitude 513.023 GPS latitude

v.p.location Home Name of current location if defined

v.p.longitude 739.006 GPS longitude


v.p.odometer 57913.1km Vehicle odometer

v.p.satcount 8 GPS satellite count in view

v.p.speed 0km/h Vehicle speed

v.p.trip 0km Trip odometer

v.t.alert 0,0,0,1 TPMS tyre alert levels [0=normal,


1=warning, 2=alert]

v.t.health 95,93,96,74% TPMS tyre health states

v.t.pressure 206.8,216.4,…kPa TPMS tyre pressures

v.t.temp 33,33,34,38°C TPMS tyre temperatures

v.type RT Vehicle type code

v.vin VF1ACVYB012345678 Vehicle identification number

19. module

20. network

21. notify

Notifications can be simple text messages or transport structured data. To distinguish by their
purpose and origin, notifications have a type and a subtype.

Notifications are sent by the module via the available communication channels (client/server


connections). If a channel is temporarily down (e.g. due to a connection loss), the notifications
for that channel will be kept in memory until the channel is available again. (Note: this
message queue does not survive a crash or reboot of the module.)

Channels process notifications differently depending on the way they work. For example, a v2
server will forward text notifications as push messages to connected smart phones and email
readers, a v3 server will publish them under an MQTT topic, and the webserver will display the
message as a modal dialog. See the respective manual sections for details.

Notification types currently defined:

 info – informational text messages


 alert – alert text messages
 error – error code messages
 data – historical data records, usually CSV formatted
 stream – live data streaming (high bandwidth), usually JSON formatted

The standard subtypes used are listed below, these can be used to filter messages. Vehicles
may introduce custom notifications and replace standard notifications, see the respective user
guide section for details.

Subtypes by convention are given in lower case, with dots ‘’.’’ as structural separators.

Notification channels currently defined:

 ovmsv2 – server v2 connection


 ovmsv3 – server v3 connection
 ovmsweb – websocket connections
 pushover – pushover text messaging service

Channels may have multiple active instances (“readers”), for example you can open multiple
websocket connections. Channels may exclude notification types. Currently  stream  records
are only supported on a websocket connection, all other types are supported on all channels.

Use  notify  status  to see the currently registered channels (“readers”). Example:

OVMS# notify status

Notification system has 3 readers registered

pushover(1): verbosity=1024

ovmsv2(2): verbosity=1024

ovmsweb(3): verbosity=65535

Notify types:

alert: 0 entries

data: 0 entries

error: 0 entries

info: 0 entries
stream: 0 entries

The channel’s “verbosity” defines the supported maximum length of a textual notification
message on that channel. Notification senders should honor this, but not all may do so. If
messages exceed this limit, they may be truncated.

Sending notifications

You can send custom notifications from the shell or command scripts by using
the  notify  raise  command. The command can send the output of another command, an
error code (implies type  error ), or any text you enter. For example, to send a custom text
message, do:
OVMS# notify raise text info usr.anton.welcome "Hello, wonderful person!"

In this case, the type would be  info  and the subtype  usr.anton.welcome . The type must
match one of the defined types, the subtype can be chosen arbitrarily. Please use a
unique  usr.  prefix for custom notifications to avoid collisions.

To send a battery status command result, do:


OVMS# notify raise command info battery.status "stat"

To send notifications from Duktape scripts, use the API call  OvmsNotify.Raise() .

Suppress notifications

You can filter the channels to be used for notifications by their subtypes. By default, no
subtypes are filtered on any channel, so all notifications are sent to all clients.

To disable (suppress) notifications, create a config entry based on the respective subtype, that
lists the channels to include or exclude:
OVMS# config set notify <subtype> <channels>

<channels> options are:

explicit inclusion: e.g.  ovmsv2,pushover  (only enable these)

explicit exclusion: e.g.  *,-ovmsv3,-ovmsweb  (only disable these)

-  (dash) to disable all

empty/ *  to enable all


Example: to disable the OTA update notifications on all channels, do:
OVMS# config set notify ota.update -

Standard notifications

Type Subtype Purpose / Content

alert alarm.sounding Vehicle alarm is sounding

alert alarm.stopped Vehicle alarm has stopped

alert batt.12v.alert 12V Battery critical

alert batt.12v.recovered 12V Battery restored

alert batt.bms.alert Battery pack/cell alert (critical


voltage/temperature deviation)
alert batt.soc.alert Battery SOC critical

info charge.done stat on charge finished

info charge.started stat on start of charge

info charge.toppingoff stat on start of topping off


charge/phase
info charge.stopped stat on planned charge stop

alert charge.stopped stat on unplanned charge stop

data debug.crash Transmit crash backtraces (→ *-


OVM-DebugCrash)
data debug.tasks Transmit task statistics (→ *-
OVM-DebugTasks)
alert flatbed.moved Vehicle is being transported
while parked - possible
theft/flatbed
info heating.started stat on start of heating (battery)

data log.grid Grid (charge/generator) history


log (see below) (→ *-LOG-Grid)
data log.trip Trip history log (see below)
(→ *-LOG-Trip)
alert modem.no_pincode No PIN code for SIM card
configured
alert modem.wrongpincode Wrong pin code

info ota.update New firmware


available/downloaded/installed
info pushover Connection failure / message
delivery response
stream retools.list.update RE toolkit CAN frame list update

stream retools.status RE toolkit general status update

info valet.disabled Valet mode disabled

info valet.enabled Valet mode enabled

alert valet.hood Vehicle hood opened while in


valet mode
alert valet.trunk Vehicle trunk opened while in
valet mode
alert vehicle.idle Vehicle is idling / stopped turned
on

Grid history log

The grid history log can be used as a source for long term statistics on your charges and typical
energy usages and to calculate your vehicle energy costs.

Log entries are created on each change of the charge or generator state
( v.c.state  /  v.g.state ).

You need to enable this log explicitly by configuring a storage time via config
param  notify  log.grid.storetime  (in days) or via the web configuration page. Set to
0/empty to disable the log. Already stored log entries will be kept on the server until expiry or
manual deletion.

Note: the stability of the total energy counters included in this log depends on their source and
persistence on the vehicle and/or module. If they are kept on the module, they may lose their
values on a power outage.

Notification subtype:  log.grid

History record type:  *-LOG-Grid

Format: CSV

Archive time: config  notify  log.grid.storetime  (days)

Fields/columns:
pos_gpslock

pos_latitude

pos_longitude

pos_altitude

pos_location

charge_type

charge_state

charge_substate

charge_mode

 charge_climit
 charge_limit_range
 charge_limit_soc
 gen_type
 gen_state
 gen_substate
 gen_mode
 gen_climit
 gen_limit_range
 gen_limit_soc
 charge_time
 charge_kwh
 charge_kwh_grid
 charge_kwh_grid_total
 gen_time
 gen_kwh
 gen_kwh_grid
 gen_kwh_grid_total
 bat_soc
 bat_range_est
 bat_range_ideal
 bat_range_full
 bat_voltage
 bat_temp
 charge_temp
 charge_12v_temp
 env_temp
 env_cabintemp
 bat_soh
 bat_health
 bat_cac
 bat_energy_used_total
 bat_energy_recd_total
 bat_coulomb_used_total
 bat_coulomb_recd_total

Trip history log

The trip history log can be used as a source for long term statistics on your trips and typical trip
power usages, as well as your battery performance in different environmental conditions and
degradation over time.

Entries are created at the beginning and end of each “ignition” cycle ( v.e.on  change).
Configure a minimum trip length for logging by the config
variable  notify  log.trip.minlength  or via the web UI. If your vehicle does not support
the  v.p.trip  metric, set the minimum trip length to 0.

The log entry at the beginning of a trip is created to track non-driving SOC changes, vampire
drains and BMS SOC corrections that occurred in between. If you’re just interested in the
actual drive results, filter the records e.g. by  pos_trip  >  0.1  or  env_drivetime  >  10  (by
default log entries will be created 3 seconds after the  v.e.on  state change).

You need to enable this log explicitly by configuring a storage time via config
param  notify  log.trip.storetime  (in days) or via the web configuration page. Set to
0/empty to disable the log. Already stored log entries will be kept on the server until expiry or
manual deletion.

Notification subtype:  log.trip

History record type:  *-LOG-Trip

Format: CSV

Archive time: config  notify  log.trip.storetime  (days)

Fields/columns:

pos_gpslock

pos_latitude

pos_longitude

pos_altitude

pos_location

pos_odometer

pos_trip

env_drivetime

env_drivemode

bat_soc

bat_range_est
bat_range_ideal

bat_range_full

bat_energy_used

bat_energy_recd

bat_coulomb_used

bat_coulomb_recd

bat_soh

bat_health

bat_cac

bat_energy_used_total

bat_energy_recd_total

bat_coulomb_used_total

bat_coulomb_recd_total

env_temp

env_cabintemp

bat_temp

inv_temp

mot_temp

charge_12v_temp

tpms_temp_min

tpms_temp_max

tpms_pressure_min

tpms_pressure_max

tpms_health_min

tpms_health_max

22. obdii

23. ota
Over The Air (OTA) Updates

OVMS v3 includes 16MB flash storage. This is partition as:

4MB for factory application image (factory)


4MB for the first OTA application image (ota_0)

4MB for a second OTA application image (ota_1)

1MB for /store configuration and scripting storage

The remainder for bootloader, generic non-volatile storage, and other data

In general, the factory application firmware is stored in flash at the factory, during module
production. That firmware is never changed on production modules, and is always kept as a
failover backup.

That leaves two firmwares for Over The Air (OTA) updates. If the currently running firmware is
the factory one, an OTA updated firmware can be written to either of the OTA partitions. If the
current running firmware is ota_0, then any new OTA updates will be written to ota_1 (and
similarly if ota_1 is currently running, then new OTA updates will be written to ota_0). In this
way, the currently running firmware is never modified and is always available as a failover
backup.

You can check the status of OTA with the ‘ota status’ command:

OVMS# ota status

Firmware: 3.1.003-2-g7ea18b4-dirty/factory/main (build idf v3.1-dev-453-


g0f978bcb Apr 7 2018 16:26:57)

Server Available: 3.1.003

Running partition: factory

Boot partition: factory

That is showing the currently running firmware as a custom image v3.1.003-2-g7ea18b4-


dirty running in factory partition. The running currently running partition is factory and the
next time the system is booted, it will run from factory as well.

As a convenience, if there is currently active wifi connectivity, a network lookup will be


performed and the currently available firmware version on the server will be shown. In this
case, that is the standard 3.1.003 release (as shown in the ‘Server Available:’ line).

If we wanted to boot from ota_1, we can do this with ‘ota boot ota_1’:

OVMS# ota boot ota_1

Boot from ota_1 at 0x00810000 (size 0x00400000)


OVMS# ota status

Firmware: 3.1.003-2-g7ea18b4-dirty/factory/main (build idf v3.1-dev-453-


g0f978bcb Apr 7 2018 16:26:57)

Server Available: 3.1.003

Running partition: factory

Boot partition: ota_1

If the bootloader fails to boot from the specified OTA firmware, it will failover and boot from
factory.

We can flash firmware to OTA either from a file on VFS (normally /sd), or over the Internet (via
http). Let’s try a simple OTA update over HTTP:

OVMS# ota flash http

Current running partition is: factory

Target partition is: ota_0

Download firmware from api.openvehicles.com/firmware/ota/v3.1/main/ovms3.bin to ota_0

Expected file size is 2100352

Preparing flash partition...

Downloading... (100361 bytes so far)

Downloading... (200369 bytes so far)

Downloading... (300577 bytes so far)

...

Downloading... (1903977 bytes so far)

Downloading... (2004185 bytes so far)

Download complete (at 2100352 bytes)

Setting boot partition...

OTA flash was successful

Flashed 2100352 bytes from api.openvehicles.com/firmware/ota/v3.1/main/ovms3.bin

Next boot will be from 'ota_0'

OVMS# ota status

Firmware: 3.1.003-2-g7ea18b4-dirty/factory/main (build idf v3.1-dev-453-


g0f978bcb Apr 7 2018 16:26:57)

Server Available: 3.1.003


Running partition: factory

Boot partition: ota_0

Rebooting now (with ‘module reset’) would boot from the new ota_0 partition firmware:

OVMS# ota status

Firmware: 3.1.003/ota_0/main (build idf v3.1-dev-453-g0f978bcb Apr 7 2018


13:11:19)

Server Available: 3.1.003

Running partition: ota_0

Boot partition: ota_0

23.1 Boot Status

OVMS maintains a record of the reason for each boot, in RAM that survives a reboot. It can
show you how long the module has been running for, and the reason for the last reboot:
OVMS# boot status

Last boot was 2244 second(s) ago

This is reset #9 since last power cycle

Detected boot reason: SoftReset

Crash counters: 0 total, 0 early

CPU#0 boot reason was 12

CPU#1 boot reason was 12

If an unexpected (not ‘module reset’) reboot occurs within the first 10 seconds of startup
(usually during the boot-time auto-loading of modules, scripts, etc), the crash counters are
incremented. If those crash counters reach 5 (without a clean reset in between), then the
auto-loading of modules is disabled for the 6th boot.

In case of a crash, the output will also contain additional debug information, i.e.:

Last crash: abort() was called on core 1

Backtrace:

0x40092ccc 0x40092ec7 0x400dbf1b 0x40176ca9 0x40176c6d 0x400eebd9 0x4013aed9

0x4013b538 0x40139c15 0x40139df9 0x4013a701 0x4013a731


If the module can access the V2 server after the crash reboot, it will also store this information
along with the crash counters in the server table “*-OVM-DebugCrash”, which will be kept on
the server for 30 days.

Please include this info when sending a bug report, along with the output of “ota status” and –
if available – any log files capturing the crash event (see Logging to SD CARD). If you can repeat
the crash, please try to capture a log at “log level verbose”.

24. power

25. pushover

26. re

27. script

28. sd

29. server

30. simcom

31. stat

32. store

33. test

34. time

35. tls

36. tpms

37. unlock

38. unvalet

39. valet

40. vehicle

41. vfs

Virtual File System (VFS)


OVMS includes a Virtual File System (VFS) used to unify all storage in the system. The primary
configuration and scripting storage is mounted as ‘/store’, and the SD card as ‘/sd’. A ‘vfs’ set
of commands is provided for basic manipulation of these stores:
OVMS# vfs ?

append VFS Append a line to a file

cat VFS Display a file

cp VFS Copy a file

edit VFS Edit a file

ls VFS Directory Listing

mkdir VFS Create a directory

mv VFS Rename a file

rm VFS Delete a file

rmdir VFS Delete a directory

stat VFS Status of a file

tail VFS Output tail of a file

Please take care. This is a very small microcontroller based system with limited storage. The
/store area should only be used for storage of configurations and small scripts. The /sd SD
CARD area is more flexibly and can be used for storing of configuration logs, firmware images,
etc.

Network Access

Network access to the VFS is available via SCP or through the web server.

SCP can access the whole file system and is read/write:

#copy a new firmware to the sd card on an OVMS named "leaf" in my ssh config

scp build/ovms3.bin leaf:/sd/dev_ovms3.bin

#copy a config backup from OVMS named "leaf" to my local directory

scp leaf:/sd/backup/cfg-2019-12-05.zip .

In the upload example the firmware can then be loaded with the  OTA flash vfs  command

The web server offers read access rooted at the sd card. An example retrieving
that same config file from the SCP example would look like:

http://leaf-abr.local/backup/cfg-2019-12-05.zip
42. wakwup

43. wifi

WiFi Networking

The OVMS WiFi system is based on the ESP32 integrated WiFi transceiver. It uses and provides
WiFi protocols 802.11 b/g/n and WPA2 authentication. The current hardware can only use 2.4
GHz frequency bands.

The WiFi antenna is built into the ESP32 module (PCB antenna). It’s possible to replace that by
an external antenna, but you’ll need electronics knowledge and SMD soldering skills &
equipment.

Client & Access Point Modes

The OVMS WiFi network can be configured as a client (connecting to existing WiFi networks)
and/or access point (providing it’s own private WiFi network). Both modes can be run
simultaneously, which is the recommended default. That way, you can always connect to your
module via WiFi.

OVMS# wifi status

Power: on

Mode: Access-Point + Client mode

STA SSID: WLAN-214677 (-78.7 dBm) [scanning]

MAC: 30:ae:a4:5f:e7:ec

IP: 192.168.2.102/255.255.255.0

GW: 192.168.2.1

AP: 7c:ff:4d:15:2f:86

AP SSID: DEX106E

MAC: 30:ae:a4:5f:e7:ed

IP: 192.168.4.1

AP Stations: 0
In client mode, the module can connect to a fixed network, or automatically scan all channels
for known networks to connect to (“scanning mode”). Scanning mode is configured by
enabling client mode without a specific client SSID.

The module will normally receive an IP address, gateway and DNS from the WiFi access point
by DHCP. See below on how to connect with a manual static IP setup.

In access point mode, the module provides access for other WiFi devices on a private network
with the IP subnet  192.168.4.0/24 . The module’s IP address on this network is  192.168.4.1 .
The module does not provide a DNS or routing to a public WiFi or GSM network on this subnet.

You can define multiple AP networks, but only one can be active at a time.

Use the  wifi  mode  command to manually set the mode, use the auto start configuration to
configure your default mode and networks.

Scanning for Networks

To manually scan your environment for available WiFi networks, do a   wifi  scan :

OVMS# wifi scan

Scanning for WIFI Access Points...

AP SSID MAC ADDRESS CHAN RSSI AUTHENTICATION

================================ ================= ==== ==== ==============

WLAN-214677 7c:ff:4d:15:2f:86 1 -83 WPA2_PSK

Telekom_FON 78:dd:12:09:dc:be 11 -84 OPEN

WLAN-184248 78:dd:12:09:dc:bc 11 -85 WPA2_PSK

===========================================================================

Scan complete: 3 access point(s) found

This can also be done in the web UI’s WiFi client network configuration page by clicking on
the  Select  button.
After the module lost connection to a network, a scan is performed automatically every 10
seconds until a new connection can be established. If you’d like to see the background scans
and results in the log, enable log level  verbose  for component  esp32wifi.
Scan Troubleshooting

If the module doesn’t find your access point, or can only see it occasionally in the scan results,
you may need to raise your scan times. This has been observed on some older Android
hotspots.

By default, the module will scan each channel for 120 milliseconds. To raise that, set your scan
time in milliseconds using the config command like this, e.g. to 200 milliseconds:

OVMS# config set network wifi.scan.tmin 200

200 milliseconds have been reported to solve the Android hotspot issue. In addition to
the  tmin  configuration you may need to allow more time looking for further access points
after finding the first one. Do so by setting   tmax , e.g.:

OVMS# config set network wifi.scan.tmax 300

Note that every increase will increase the time a full scan takes, so don’t set too high values.
Too high values may result in connection drops on the AP network of the module.

WiFi Signal Quality

The module monitors the WiFi client signal quality and drops a WiFi connection (switches to
modem if available) if it becomes too bad. The WiFi connection will be kept active and
monitored, and as the signal recovers, the module will automatically reconnect to the AP.

The default threshold is to stop using the connection if it drops below -89 dBm. A connection is
assumed to be usable if the signal is above -87 dBm.

Depending on your WiFi environment, the WiFi connection may still be usable at lower signal
levels.

To tweak the thresholds, use the web UI WiFi configuration or change the following
configuration variables:

OVMS# config set network wifi.sq.good -87.0

OVMS# config set network wifi.sq.bad -89.0


WiFi Mesh Configuration

In normal operation, the module will try to stick to an established connection as long as
possible. If signal quality drops, it will switch to the modem connection, but monitor the WiFi
signal and reassociate to the current AP if possible.

If using a mesh network, you may want to force scanning for a better mesh AP as soon as the
signal drops below the “bad” threshold. To do so, set the network configuration
wifi.bad.reconnect to true, either using the web UI or by doing:

OVMS# config set network wifi.bad.reconnect yes

With this, the module will perform a full WiFi reconnect cycle as soon as the signal becomes
bad.

Static IP / SSID Configuration

To connect with a static client address instead of using DHCP, use


the  wifi ip static  command:

OVMS# wifi ip static [<ip> <subnet> <gateway>]

The gateway will also be used as the DNS.

To configure persistent static details for a known SSID, set these using the following
configuration syntax:

OVMS# config set wifi.ssid "<ssid>.ovms.staticip" "<ip>,<subnet>,<gateway>"

You can also force connection to a specific AP by it’s MAC address, “BSSID” in WiFi terms. To
do so, you need to supply the MAC address as a second argument to the  wifi mode client  or
as the third argument to the  wifi mode apclient  command:

OVMS# wifi mode client <ssid> <bssid>


OVMS# wifi mode apclient <apssid> <ssid> <bssid>

This currently needs manual activation by command. Hint: use a script, for example bound to a
location.

AP Bandwidth Configuration

In normal operation, the default AP bandwidth is set to 20Mhz to reduce interference and
improve the signal quality. If a wider 40Mhz bandwidth is preferred, eg for high throughput
logging, set the network configuration  wifi.ap.bw  with the command:

OVMS# config set network wifi.ap.bw 40

Once the parameter is set the module will require rebooting to take effect. The default
bandwidth can be restored by either removing the parameter or setting it to 20.

You might also like