Skip to content

Commit dbc343c

Browse files
committed
Added product names.
1 parent 06717e5 commit dbc343c

File tree

2 files changed

+212
-12
lines changed

2 files changed

+212
-12
lines changed

app/dmved.f90

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,13 @@ integer function run(app, tty) result(rc)
242242
!! Connects to TTY and runs an event loop to read VE.Direct frames to
243243
!! responses. The observation is then forwarded via message queue to
244244
!! the specified receiver.
245-
type(app_type), intent(inout) :: app !! App settings.
246-
type(tty_type), intent(inout) :: tty !! TTY settings.
245+
type(app_type), intent(inout) :: app !! App type.
246+
type(tty_type), intent(inout) :: tty !! TTY type.
247+
248+
character(len=VE_PRODUCT_NAME_LEN) :: product_name
247249

248250
character :: byte
249-
integer :: code
250-
integer :: field_type
251+
integer :: code, field_type, pid
251252
integer(kind=i8) :: epoch_last, epoch_now
252253
logical :: eor, finished, valid
253254
logical :: debug, has_receiver
@@ -260,6 +261,7 @@ integer function run(app, tty) result(rc)
260261
debug = (app%debug .or. app%verbose)
261262
call logger%info('started ' // APP_NAME)
262263

264+
product_name = ' '
263265
epoch_last = 0_i8
264266
has_receiver = (len_trim(app%receiver) > 0)
265267

@@ -323,10 +325,23 @@ integer function run(app, tty) result(rc)
323325
if (frame%label == 'SER#') cycle tty_loop ! Ignore serial number field.
324326
if (frame%label == 'ERR') code = dm_atoi(frame%value) ! Save device error.
325327

328+
! Log device error.
326329
if (dm_ve_is_error(code)) then
327330
call logger%warning(dm_ve_error_message(code), error=E_SENSOR)
328331
end if
329332

333+
! Find product name of connected VE device.
334+
if (frame%label == 'PID' .and. product_name == ' ') then
335+
call dm_hex_to_int(frame%value, pid)
336+
rc = dm_ve_product_name(pid, product_name)
337+
338+
if (dm_is_error(rc)) then
339+
call logger%warning('connected to unknown Victron Energy device', error=rc)
340+
else
341+
call logger%info('connected to Victron Energy ' // product_name)
342+
end if
343+
end if
344+
330345
! VE.Direct frame to response.
331346
call dm_ve_frame_read(frame, response, field_type, error=rc)
332347

@@ -350,8 +365,8 @@ end function run
350365
subroutine create_observ(observ, app, responses)
351366
!! Creates new observation from VE.Direct responses.
352367
type(observ_type), intent(out) :: observ !! Created observation.
353-
type(app_type), intent(inout) :: app !! App settings.
354-
type(response_type), intent(inout) :: responses(:) !! All VE.Direct responses.
368+
type(app_type), intent(inout) :: app !! App type.
369+
type(response_type), intent(inout) :: responses(:) !! All captured VE.Direct responses.
355370

356371
character(len=TIME_LEN) :: timestamp
357372
integer :: rc
@@ -442,7 +457,7 @@ end subroutine create_observ
442457

443458
subroutine signal_callback(signum) bind(c)
444459
!! Default POSIX signal handler of the program.
445-
integer(kind=c_int), intent(in), value :: signum
460+
integer(kind=c_int), intent(in), value :: signum !! Signal number.
446461

447462
select case (signum)
448463
case default

src/dm_ve.f90

Lines changed: 190 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,11 @@ module dm_ve
284284
] !! Device names.
285285

286286
! Character lenghts.
287-
integer, parameter, public :: VE_LABEL_LEN = 8 !! Max. field label length (minus newline).
288-
integer, parameter, public :: VE_NAME_LEN = RESPONSE_NAME_LEN !! Max. response name length.
289-
integer, parameter, public :: VE_UNIT_LEN = RESPONSE_UNIT_LEN !! Max. field unit length.
290-
integer, parameter, public :: VE_VALUE_LEN = 32 !! Max. field value length (minus tab).
287+
integer, parameter, public :: VE_LABEL_LEN = 8 !! Max. field label length (minus newline).
288+
integer, parameter, public :: VE_NAME_LEN = RESPONSE_NAME_LEN !! Max. response name length.
289+
integer, parameter, public :: VE_UNIT_LEN = RESPONSE_UNIT_LEN !! Max. field unit length.
290+
integer, parameter, public :: VE_VALUE_LEN = 32 !! Max. field value length (minus tab).
291+
integer, parameter, public :: VE_PRODUCT_NAME_LEN = 38 !! Max. product name length.
291292

292293
! TTY parameters.
293294
integer, parameter, public :: VE_TTY_ACCESS = TTY_RDONLY !! Default TTY access mode.
@@ -322,6 +323,12 @@ module dm_ve
322323
character(len=VE_VALUE_LEN) :: value = ' ' !! Field value.
323324
end type ve_field_type
324325

326+
type, public :: ve_product_type
327+
!! Victron product id and name.
328+
integer :: pid = 0 !! Product id.
329+
character(len=VE_PRODUCT_NAME_LEN) :: name = ' ' !! Product name.
330+
end type ve_product_type
331+
325332
! Supported VE.Direct field types.
326333
integer, parameter, public :: VE_FIELD_NONE = 0 !! None (invalid).
327334
integer, parameter, public :: VE_FIELD_ALARM = 1 !! [ SS ] Alarm condition active (ON/OFF).
@@ -372,7 +379,7 @@ module dm_ve
372379
integer, parameter, public :: VE_FIELD_VS = 46 !! [ SS ] Auxiliary (starter) voltage.
373380
integer, parameter, public :: VE_FIELD_LAST = 46 !! Never use this.
374381

375-
! VE.Direct default fields (MPPT only).
382+
! VE.Direct default fields (MPPT and SmartShunt only).
376383
integer, parameter, public :: VE_NFIELDS = VE_FIELD_LAST !! Number of supported fields.
377384

378385
type(ve_field_type), parameter, public :: VE_FIELDS(VE_NFIELDS) = [ &
@@ -424,6 +431,162 @@ module dm_ve
424431
ve_field_type('VS', 'vs', 'mV', RESPONSE_TYPE_INT32) &
425432
] !! Predefined fields.
426433

434+
! VE.Direct default products.
435+
integer, parameter, public :: VE_NPRODUCTS = 150 !! Number of VE products.
436+
437+
type(ve_product_type), parameter, public :: VE_PRODUCTS(VE_NPRODUCTS) = [ &
438+
ve_product_type(int(z'0203'), 'BMV-700'), &
439+
ve_product_type(int(z'0204'), 'BMV-702'), &
440+
ve_product_type(int(z'0205'), 'BMV-700H'), &
441+
ve_product_type(int(z'0300'), 'BlueSolar MPPT 70|15'), &
442+
ve_product_type(int(z'A040'), 'BlueSolar MPPT 75|50'), &
443+
ve_product_type(int(z'A041'), 'BlueSolar MPPT 150|35'), &
444+
ve_product_type(int(z'A042'), 'BlueSolar MPPT 75|15'), &
445+
ve_product_type(int(z'A043'), 'BlueSolar MPPT 100|15'), &
446+
ve_product_type(int(z'A044'), 'BlueSolar MPPT 100|30'), &
447+
ve_product_type(int(z'A045'), 'BlueSolar MPPT 100|50'), &
448+
ve_product_type(int(z'A046'), 'BlueSolar MPPT 150|70'), &
449+
ve_product_type(int(z'A047'), 'BlueSolar MPPT 150|100'), &
450+
ve_product_type(int(z'A049'), 'BlueSolar MPPT 100|50 rev2'), &
451+
ve_product_type(int(z'A04A'), 'BlueSolar MPPT 100|30 rev2'), &
452+
ve_product_type(int(z'A04B'), 'BlueSolar MPPT 150|35 rev2'), &
453+
ve_product_type(int(z'A04C'), 'BlueSolar MPPT 75|10'), &
454+
ve_product_type(int(z'A04D'), 'BlueSolar MPPT 150|45'), &
455+
ve_product_type(int(z'A04E'), 'BlueSolar MPPT 150|60'), &
456+
ve_product_type(int(z'A04F'), 'BlueSolar MPPT 150|85'), &
457+
ve_product_type(int(z'A050'), 'SmartSolar MPPT 250|100'), &
458+
ve_product_type(int(z'A051'), 'SmartSolar MPPT 150|100'), &
459+
ve_product_type(int(z'A052'), 'SmartSolar MPPT 150|85'), &
460+
ve_product_type(int(z'A053'), 'SmartSolar MPPT 75|15'), &
461+
ve_product_type(int(z'A054'), 'SmartSolar MPPT 75|10'), &
462+
ve_product_type(int(z'A055'), 'SmartSolar MPPT 100|15'), &
463+
ve_product_type(int(z'A056'), 'SmartSolar MPPT 100|30'), &
464+
ve_product_type(int(z'A057'), 'SmartSolar MPPT 100|50'), &
465+
ve_product_type(int(z'A058'), 'SmartSolar MPPT 150|35'), &
466+
ve_product_type(int(z'A059'), 'SmartSolar MPPT 150|100 rev2'), &
467+
ve_product_type(int(z'A05A'), 'SmartSolar MPPT 150|85 rev2'), &
468+
ve_product_type(int(z'A05B'), 'SmartSolar MPPT 250|70'), &
469+
ve_product_type(int(z'A05C'), 'SmartSolar MPPT 250|85'), &
470+
ve_product_type(int(z'A05D'), 'SmartSolar MPPT 250|60'), &
471+
ve_product_type(int(z'A05E'), 'SmartSolar MPPT 250|45'), &
472+
ve_product_type(int(z'A05F'), 'SmartSolar MPPT 100|20'), &
473+
ve_product_type(int(z'A060'), 'SmartSolar MPPT 100|20 48V'), &
474+
ve_product_type(int(z'A061'), 'SmartSolar MPPT 150|45'), &
475+
ve_product_type(int(z'A062'), 'SmartSolar MPPT 150|60'), &
476+
ve_product_type(int(z'A063'), 'SmartSolar MPPT 150|70'), &
477+
ve_product_type(int(z'A064'), 'SmartSolar MPPT 250|85 rev2'), &
478+
ve_product_type(int(z'A065'), 'SmartSolar MPPT 250|100 rev2'), &
479+
ve_product_type(int(z'A066'), 'BlueSolar MPPT 100|20'), &
480+
ve_product_type(int(z'A067'), 'BlueSolar MPPT 100|20 48V'), &
481+
ve_product_type(int(z'A068'), 'SmartSolar MPPT 250|60 rev2'), &
482+
ve_product_type(int(z'A069'), 'SmartSolar MPPT 250|70 rev2'), &
483+
ve_product_type(int(z'A06A'), 'SmartSolar MPPT 150|45 rev2'), &
484+
ve_product_type(int(z'A06B'), 'SmartSolar MPPT 150|60 rev2'), &
485+
ve_product_type(int(z'A06C'), 'SmartSolar MPPT 150|70 rev2'), &
486+
ve_product_type(int(z'A06D'), 'SmartSolar MPPT 150|85 rev3'), &
487+
ve_product_type(int(z'A06E'), 'SmartSolar MPPT 150|100 rev3'), &
488+
ve_product_type(int(z'A06F'), 'BlueSolar MPPT 150|45 rev2'), &
489+
ve_product_type(int(z'A070'), 'BlueSolar MPPT 150|60 rev2'), &
490+
ve_product_type(int(z'A071'), 'BlueSolar MPPT 150|70 rev2'), &
491+
ve_product_type(int(z'A072'), 'BlueSolar MPPT 150/45 rev3'), &
492+
ve_product_type(int(z'A073'), 'SmartSolar MPPT 150/45 rev3'), &
493+
ve_product_type(int(z'A074'), 'SmartSolar MPPT 75/10 rev2'), &
494+
ve_product_type(int(z'A075'), 'SmartSolar MPPT 75/15 rev2'), &
495+
ve_product_type(int(z'A076'), 'BlueSolar MPPT 100/30 rev3'), &
496+
ve_product_type(int(z'A077'), 'BlueSolar MPPT 100/50 rev3'), &
497+
ve_product_type(int(z'A078'), 'BlueSolar MPPT 150/35 rev3'), &
498+
ve_product_type(int(z'A079'), 'BlueSolar MPPT 75/10 rev2'), &
499+
ve_product_type(int(z'A07A'), 'BlueSolar MPPT 75/15 rev2'), &
500+
ve_product_type(int(z'A07B'), 'BlueSolar MPPT 100/15 rev2'), &
501+
ve_product_type(int(z'A07C'), 'BlueSolar MPPT 75/10 rev3'), &
502+
ve_product_type(int(z'A07D'), 'BlueSolar MPPT 75/15 rev3'), &
503+
ve_product_type(int(z'A07E'), 'SmartSolar MPPT 100/30 12V'), &
504+
ve_product_type(int(z'A07F'), 'All-In-1 SmartSolar MPPT 75/15 12V'), &
505+
ve_product_type(int(z'A102'), 'SmartSolar MPPT VE.Can 150/70'), &
506+
ve_product_type(int(z'A103'), 'SmartSolar MPPT VE.Can 150/45'), &
507+
ve_product_type(int(z'A104'), 'SmartSolar MPPT VE.Can 150/60'), &
508+
ve_product_type(int(z'A105'), 'SmartSolar MPPT VE.Can 150/85'), &
509+
ve_product_type(int(z'A106'), 'SmartSolar MPPT VE.Can 150/100'), &
510+
ve_product_type(int(z'A107'), 'SmartSolar MPPT VE.Can 250/45'), &
511+
ve_product_type(int(z'A108'), 'SmartSolar MPPT VE.Can 250/60'), &
512+
ve_product_type(int(z'A109'), 'SmartSolar MPPT VE.Can 250/70'), &
513+
ve_product_type(int(z'A10A'), 'SmartSolar MPPT VE.Can 250/85'), &
514+
ve_product_type(int(z'A10B'), 'SmartSolar MPPT VE.Can 250/100'), &
515+
ve_product_type(int(z'A10C'), 'SmartSolar MPPT VE.Can 150/70 rev2'), &
516+
ve_product_type(int(z'A10D'), 'SmartSolar MPPT VE.Can 150/85 rev2'), &
517+
ve_product_type(int(z'A10E'), 'SmartSolar MPPT VE.Can 150/100 rev2'), &
518+
ve_product_type(int(z'A10F'), 'BlueSolar MPPT VE.Can 150/100'), &
519+
ve_product_type(int(z'A112'), 'BlueSolar MPPT VE.Can 250/70'), &
520+
ve_product_type(int(z'A113'), 'BlueSolar MPPT VE.Can 250/100'), &
521+
ve_product_type(int(z'A114'), 'SmartSolar MPPT VE.Can 250/70 rev2'), &
522+
ve_product_type(int(z'A115'), 'SmartSolar MPPT VE.Can 250/100 rev2'), &
523+
ve_product_type(int(z'A116'), 'SmartSolar MPPT VE.Can 250/85 rev2'), &
524+
ve_product_type(int(z'A117'), 'BlueSolar MPPT VE.Can 150/100 rev2'), &
525+
ve_product_type(int(z'A201'), 'Phoenix Inverter 12V 250VA 230V'), &
526+
ve_product_type(int(z'A202'), 'Phoenix Inverter 24V 250VA 230V'), &
527+
ve_product_type(int(z'A204'), 'Phoenix Inverter 48V 250VA 230V'), &
528+
ve_product_type(int(z'A211'), 'Phoenix Inverter 12V 375VA 230V'), &
529+
ve_product_type(int(z'A212'), 'Phoenix Inverter 24V 375VA 230V'), &
530+
ve_product_type(int(z'A214'), 'Phoenix Inverter 48V 375VA 230V'), &
531+
ve_product_type(int(z'A221'), 'Phoenix Inverter 12V 500VA 230V'), &
532+
ve_product_type(int(z'A222'), 'Phoenix Inverter 24V 500VA 230V'), &
533+
ve_product_type(int(z'A224'), 'Phoenix Inverter 48V 500VA 230V'), &
534+
ve_product_type(int(z'A231'), 'Phoenix Inverter 12V 250VA 230V'), &
535+
ve_product_type(int(z'A232'), 'Phoenix Inverter 24V 250VA 230V'), &
536+
ve_product_type(int(z'A234'), 'Phoenix Inverter 48V 250VA 230V'), &
537+
ve_product_type(int(z'A239'), 'Phoenix Inverter 12V 250VA 120V'), &
538+
ve_product_type(int(z'A23A'), 'Phoenix Inverter 24V 250VA 120V'), &
539+
ve_product_type(int(z'A23C'), 'Phoenix Inverter 48V 250VA 120V'), &
540+
ve_product_type(int(z'A241'), 'Phoenix Inverter 12V 375VA 230V'), &
541+
ve_product_type(int(z'A242'), 'Phoenix Inverter 24V 375VA 230V'), &
542+
ve_product_type(int(z'A244'), 'Phoenix Inverter 48V 375VA 230V'), &
543+
ve_product_type(int(z'A249'), 'Phoenix Inverter 12V 375VA 120V'), &
544+
ve_product_type(int(z'A24A'), 'Phoenix Inverter 24V 375VA 120V'), &
545+
ve_product_type(int(z'A24C'), 'Phoenix Inverter 48V 375VA 120V'), &
546+
ve_product_type(int(z'A251'), 'Phoenix Inverter 12V 500VA 230V'), &
547+
ve_product_type(int(z'A252'), 'Phoenix Inverter 24V 500VA 230V'), &
548+
ve_product_type(int(z'A254'), 'Phoenix Inverter 48V 500VA 230V'), &
549+
ve_product_type(int(z'A259'), 'Phoenix Inverter 12V 500VA 120V'), &
550+
ve_product_type(int(z'A25A'), 'Phoenix Inverter 24V 500VA 120V'), &
551+
ve_product_type(int(z'A25C'), 'Phoenix Inverter 48V 500VA 120V'), &
552+
ve_product_type(int(z'A261'), 'Phoenix Inverter 12V 800VA 230V'), &
553+
ve_product_type(int(z'A262'), 'Phoenix Inverter 24V 800VA 230V'), &
554+
ve_product_type(int(z'A264'), 'Phoenix Inverter 48V 800VA 230V'), &
555+
ve_product_type(int(z'A269'), 'Phoenix Inverter 12V 800VA 120V'), &
556+
ve_product_type(int(z'A26A'), 'Phoenix Inverter 24V 800VA 120V'), &
557+
ve_product_type(int(z'A26C'), 'Phoenix Inverter 48V 800VA 120V'), &
558+
ve_product_type(int(z'A271'), 'Phoenix Inverter 12V 1200VA 230V'), &
559+
ve_product_type(int(z'A272'), 'Phoenix Inverter 24V 1200VA 230V'), &
560+
ve_product_type(int(z'A274'), 'Phoenix Inverter 48V 1200VA 230V'), &
561+
ve_product_type(int(z'A279'), 'Phoenix Inverter 12V 1200VA 120V'), &
562+
ve_product_type(int(z'A27A'), 'Phoenix Inverter 24V 1200VA 120V'), &
563+
ve_product_type(int(z'A27C'), 'Phoenix Inverter 48V 1200VA 120V'), &
564+
ve_product_type(int(z'A281'), 'Phoenix Inverter 12V 1600VA 230V'), &
565+
ve_product_type(int(z'A282'), 'Phoenix Inverter 24V 1600VA 230V'), &
566+
ve_product_type(int(z'A284'), 'Phoenix Inverter 48V 1600VA 230V'), &
567+
ve_product_type(int(z'A291'), 'Phoenix Inverter 12V 2000VA 230V'), &
568+
ve_product_type(int(z'A292'), 'Phoenix Inverter 24V 2000VA 230V'), &
569+
ve_product_type(int(z'A294'), 'Phoenix Inverter 48V 2000VA 230V'), &
570+
ve_product_type(int(z'A2A1'), 'Phoenix Inverter 12V 3000VA 230V'), &
571+
ve_product_type(int(z'A2A2'), 'Phoenix Inverter 24V 3000VA 230V'), &
572+
ve_product_type(int(z'A2A4'), 'Phoenix Inverter 48V 3000VA 230V'), &
573+
ve_product_type(int(z'A340'), 'Phoenix Smart IP43 Charger 12|50 (1+1)'), &
574+
ve_product_type(int(z'A341'), 'Phoenix Smart IP43 Charger 12|50 (3)'), &
575+
ve_product_type(int(z'A342'), 'Phoenix Smart IP43 Charger 24|25 (1+1)'), &
576+
ve_product_type(int(z'A343'), 'Phoenix Smart IP43 Charger 24|25 (3)'), &
577+
ve_product_type(int(z'A344'), 'Phoenix Smart IP43 Charger 12|30 (1+1)'), &
578+
ve_product_type(int(z'A345'), 'Phoenix Smart IP43 Charger 12|30 (3)'), &
579+
ve_product_type(int(z'A346'), 'Phoenix Smart IP43 Charger 24|16 (1+1)'), &
580+
ve_product_type(int(z'A347'), 'Phoenix Smart IP43 Charger 24|16 (3)'), &
581+
ve_product_type(int(z'A381'), 'BMV-712 Smart'), &
582+
ve_product_type(int(z'A382'), 'BMV-710H Smart'), &
583+
ve_product_type(int(z'A383'), 'BMV-712 Smart rev2'), &
584+
ve_product_type(int(z'A389'), 'SmartShunt 500A/50mV'), &
585+
ve_product_type(int(z'A38A'), 'SmartShunt 1000A/50mV'), &
586+
ve_product_type(int(z'A38B'), 'SmartShunt 2000A/50mV'), &
587+
ve_product_type(int(z'A3F0'), 'Smart BuckBoost 12V/12V-50A') &
588+
] !! Predefined products.
589+
427590
public :: dm_ve_device_from_name
428591
public :: dm_ve_device_is_valid
429592
public :: dm_ve_error_message
@@ -433,6 +596,7 @@ module dm_ve
433596
public :: dm_ve_frame_read
434597
public :: dm_ve_frame_reset
435598
public :: dm_ve_is_error
599+
public :: dm_ve_product_name
436600
contains
437601
! **************************************************************************
438602
! PUBLIC FUNCTIONS.
@@ -550,6 +714,27 @@ pure elemental logical function dm_ve_is_valid_field_type(type) result(valid)
550714
valid = (type > VE_FIELD_NONE .and. type <= VE_FIELD_LAST)
551715
end function dm_ve_is_valid_field_type
552716

717+
integer function dm_ve_product_name(pid, name) result(rc)
718+
!! Returns name of Victron Energy product associated with given PID in
719+
!! dummy argument `name`. Returns `E_NOT_FOUND` and sets name to `N/A`
720+
!! on error.
721+
integer, intent(in) :: pid !! Product ID.
722+
character(len=VE_PRODUCT_NAME_LEN), intent(out) :: name !! Product name.
723+
724+
integer :: i
725+
726+
rc = E_NOT_FOUND
727+
name = 'N/A'
728+
729+
do i = 1, VE_NPRODUCTS
730+
if (pid == VE_PRODUCTS(i)%pid) then
731+
rc = E_NONE
732+
name = VE_PRODUCTS(i)%name
733+
return
734+
end if
735+
end do
736+
end function dm_ve_product_name
737+
553738
! **************************************************************************
554739
! PUBLIC SUBROUTINES.
555740
! **************************************************************************

0 commit comments

Comments
 (0)