Neueste Beiträge

#91
oscat.lib fuer PC WorX/MULTIPROG / Re: PC WORX: SMTP_CLIENT geht ...
Letzter Beitrag von peewit - 08. November 2022, 08:10:43
Hi cole_joos

It looks like your controller does not support SSL/TLS.

Sending emails via HTTPS (encrypted) is only supported for Phoenix Contact ILC 1xx controllers. The controllers support HTTPS from firmware version 4.20 or higher and from PC Worx version 6.30.767 or higher (part of AUTOMATIONWORX Software Suite 1.81 including AddOn V1). Only if you have such a controller with suitable firmware, you can use encryption at all.

GMAIL compatibility
Because Gmail always works with maximum security and older SSL/TLS
protocols may not be supported anymore it may be necessary to build the
settings for the SMTP_CLIENT module on the Gmail account.
have to be made. A special hint for this is the SMTP error code 534
at Gmail. Some apps and devices use less secure login technologies.
This makes your account more vulnerable to attack. You can disable access for these apps
disable access for these apps (recommended) or enable access if you want to use the apps
despite the risk.
https://support.google.com/accounts/answer/6010255?hl=de

Link for setting change
https://www.google.com/settings/security/lesssecureapps
Access for less secure apps -> Enable


URL example:
TLS://username:password@smtp_server


If all this is not the case then your only option is to use an unencrypted SMTP server via PORT 25. Unfortunately there are only very few providers that still support this.
#92
Modulentwicklung / Re: Neuer Wetter-Baustein für ...
Letzter Beitrag von mattsches - 24. Oktober 2022, 21:51:04
Der Baustein werkelt bei mir noch ohne Probleme. Weatherbit.io bieten weiterhin einen kostenfreien Zugang an, der für den Baustein auch ausreicht (wenn bzgl. der abrufbaren Daten nichts geändert wurde). Also einfach registrieren, API Key holen und ausprobieren.

Für die PV-Prognose würde ich mir mal http://forecast.solar/ anschauen. Dort bekommst du einen tatsächlichen Ertag in kWh für den Folgetag prognostiziert. Wie gut, kann ich nicht beurteilen, habe das (noch) nicht im Einsatz. Die API liefert m. W. eine JSON-Antwort, der Weatherbit-Baustein ließe sich also als Grundlage für eine Abfrage nehmen.
#93
oscat.lib fuer Step 7 / Re: Problem: LINEAR_INT aus SC...
Letzter Beitrag von Zatras - 24. Oktober 2022, 17:57:23
Hallo Forum,

nach einigen Jahren habe ich wieder mal ein kleines Problem mit der OSCAT-Funktion  LINEAR_INT  (Stand vom 29.08.13 von Gregor)  unter TIA V15.1.

..-erledigt..
#94
Modulentwicklung / Re: Neuer Wetter-Baustein für ...
Letzter Beitrag von Hgo - 22. Oktober 2022, 17:28:02
Hallo,
funktioniert der Baustein mit dem Anbieter noch? Oder kann man sich die Mühe sparen?

Ich suche eigentlich eine Möglichkeit den PV Ertrag der nächsten Stunden abzuschätzen. Wenn jemand eine besser Idee als die Wettervorhersage hat wäre ich nicht Böse ;)
#96
Bestehende Module / Existing Modules / Re: Probleme mit Meter, nach e...
Letzter Beitrag von Oberchefe - 15. Oktober 2022, 22:25:45
auch wenn der Beitrag schon etwas älter ist, am Bausteinproblem hat sich noch nichts geändert. Ursache und Abhilfe siehe hier:
https://www.sps-forum.de/threads/baustein-w%C3%A4rmemengenz%C3%A4hler.109203/
#97
oscat.lib fuer CoDeSys 3 / Oscar basic 64bits?
Letzter Beitrag von galexis - 13. Oktober 2022, 14:22:46
Hi, there is 64bits version of oscat basic for codesys 3.5sp18-3 64bits?
Impossible to install 32bits version...
Thanks for your help.
#98
oscat.lib fuer CoDeSys 3 / Re: FTP funktioniert mit OSCAT...
Letzter Beitrag von mauskopf - 13. Oktober 2022, 10:41:40
Habe ich was falsch gemacht bei meiner Frage Stellung?
#99
oscat.lib fuer CoDeSys 3 / FTP funktioniert mit OSCATNetw...
Letzter Beitrag von mauskopf - 13. Oktober 2022, 09:35:21
Guten Morgen,
ich bin ganz neu hier.
Ich habe mir die OSCATNetwork LIB geholt da ich die Notwendigkeit habe von meiner Berghof SPS per FTP ein CSV File zu übertragen.
Leider mache ich Irgendwas falsch da es nicht funktioniert.

Ich bekomme folgende Fehler Meldung.
ERROR_C gibt 16#FF000000
ERROR_T gibt 16#03

Was mache ich falsch bzw wie kann ich den Fehler debugen?
#100
Modulentwicklung / Re: Neuer Baustein zum Parsen ...
Letzter Beitrag von mattsches - 11. Oktober 2022, 20:41:56
Update, falls jemand außer mir den Baustein im Einsatz haben sollte: Das gute Stück kam nicht mit negativen Werte und leeren Objekten ( {} )  klar, wie mir erst jetzt aufgefallen ist, wo ich ebenfalls einen Fronius-Wechselrichter damit anzapfen wollte. Anbei eine überarbeitete Version, mit der das bei mir nun funktioniert. Ursprünglich wollte ich eine Datei anhängen, doch die Funktion hier im Forum scheint abgedreht worden zu sein. Daher etwas umständlicher als Quelltext:

Deklaration:

FUNCTION_BLOCK JSON_READER
VAR CONSTANT
MAX_LEVEL : UINT := 19;
END_VAR

VAR_INPUT
RST : BOOL := TRUE; (* reset *)
WATCHDOG : TIME := t#1ms; (* watchdog time *)
START_POS : UINT := 0; (* first byte in network buffer to be processed *)
STOP_POS : UINT := 0; (* last byte in network buffer to be processed *)
BUF : NW_BUF_LONG; (* network buffer that contains the JSON string as byte stream *)
END_VAR

VAR_OUTPUT
COUNT : UINT := 0; (* number of parsed JSON elements *)
LEVEL : UINT := 0; (* nesting level of current JSON element *)
ARRAY_INDEX : ARRAY[1..MAX_LEVEL] OF INT := MAX_LEVEL(-1); (* current array index value (-1: element is not part of an array) *)
PATH : STRING(STRING_LENGTH); (* full path of current JSON element *)
ELEMENT : STRING(STRING_LENGTH); (* name of current JSON element *)
VALUE : STRING(STRING_LENGTH); (* value of current JSON element *)
NEW_DATA : BOOL := FALSE; (* new data is available (next element has been parsed *)
DONE : BOOL := FALSE; (* last element has been parsed *)
ERROR : BOOL := FALSE; (* error occured, see status for details; reset is required *)
STATUS : BYTE := 0; (* ESR compatible status output ( 0=ok,
  1=error: dot not found in path string,
  2=error: closing square bracket not found in path string,
  3=max. nesting level exceeded,
100=element has been parsed,
101=watchdog timer expired *)
END_VAR

VAR
CurrentByte : UINT; (* index of currently scanned byte in network buffer *)
ObjectEmpty : BOOL := FALSE; (* current object is still empty *)
LookForValue : BOOL := FALSE; (* colon has been found, now look for value *)
FirstByte : UINT := 0; (* first byte of string to be extracted from buffer *)
LastByte : UINT := 0; (* last byte of string to be extracted from buffer *)
ElementParsed : BOOL := FALSE; (* element has been parsed *)
PathOverflow : BOOL := FALSE; (* maximum string length exceeded for path variable *)

StringFound : INT := 0; (* position of string within another string *)
LoopCount : INT := 0; (* loop counter *)
WatchdogTimer : TON; (* watchdog timer *)

_Level : UINT := 0; (* nesting level of current JSON element *)
_Path : STRING(STRING_LENGTH); (* full path of current JSON element *)
_ArrayIndex : ARRAY[1..MAX_LEVEL] OF INT := MAX_LEVEL(-1); (* current array index value (-1: element is not part of an array) *)
_Element : STRING(STRING_LENGTH); (* name of current JSON element *)
_Value : STRING(STRING_LENGTH); (* value of current JSON element *)

pValueString : POINTER TO ARRAY[0..STRING_LENGTH] OF BYTE;
END_VAR


(*

version 1.1 11 oct 2022
programmer md
tested by md

JSON_READER allows to parse a JSON string stored in a byte array (buffer) and extract the JSON elements one after another.

The parsing is monitored by a watchdog timer such that the block does cause a delay of the PLC program of more than the
configured time. The block further automatically interrupts the parsing as soon as an element and its value have been found.
It then provides both at the CTRL structured variable for external processing and continues to search for the next element
when it is called again (next cycle).

Values are always provided as strings, conversion to numeric data types needs to be done by the calling program.

*)



Code:

(* reset/initialize *)
IF RST THEN
CurrentByte := START_POS;
ObjectEmpty := FALSE;
LookForValue := FALSE;
FirstByte := 0;
LastByte := 0;

FOR LoopCount := 1 TO MAX_LEVEL DO
_ArrayIndex[LoopCount] := -1;
END_FOR

ElementParsed := FALSE;
PathOverflow := FALSE;

_Level := 0;
_Element := '';
_Path := '';
_Value := '';

COUNT := 0;
LEVEL := 0;
ELEMENT := '';
PATH := '';
VALUE := '';
NEW_DATA := FALSE;
DONE := FALSE;
ERROR := FALSE;
STATUS := 0;
END_IF;


(* reset watchdog timer *)
WatchdogTimer(IN:=FALSE , PT:= WATCHDOG, Q=> , ET=> );

(* reset new data flag *)
NEW_DATA := FALSE;

(* loop through buffer until buffer end reached OR element has been parsed OR watchdog timer has expired *)
WHILE (CurrentByte <= STOP_POS AND NOT ElementParsed AND NOT WatchdogTimer.Q AND NOT ERROR AND NOT RST AND NOT DONE) DO

WatchdogTimer(IN:=TRUE , PT:= WATCHDOG, Q=> , ET=> ); (* call watchdog timer *)

CASE BUF[CurrentByte] OF (* evaluate current character *)

0: (* end of string *)
DONE := TRUE;

123: (* '{' object start *)
IF _Level < MAX_LEVEL THEN
_Level := _Level + 1;
ObjectEmpty := TRUE;
LookForValue := FALSE;
FirstByte := 0;
_Element := '';
_Value := '';
ELSE
ERROR := TRUE;
STATUS := 3;
END_IF

125: (* '}' object end *)
IF LookForValue AND _Value <> '' THEN (* element has been parsed *)
ElementParsed := TRUE;
EXIT; (* exit loop immediately in order to first copy the element details to the output parameters *)
END_IF

IF _Level > 1 AND NOT PathOverflow THEN
_Element := '';
_Value := '';
_Level := _Level - 1; (* up one level *)
LookForValue := FALSE; (* next string must be a key, not a value *)
FirstByte := 0;

IF NOT ObjectEmpty THEN (* don't change path if current object is still empty, i. e. nothing has been appended to the path before *)
StringFound := FINDB(_Path, '.');
IF StringFound > 1 THEN
_Path := LEFT(_Path, StringFound - 1); (* remove last element from path string *)
ELSE (* error: dot has not been found *)
ERROR := TRUE;
STATUS := 1;
END_IF
END_IF

ObjectEmpty := FALSE;
END_IF

91: (* '[' array start *)
IF LEN(_Path) + 3 < STRING_LENGTH AND NOT PathOverflow THEN
_Path := CONCAT(_Path, '[0]'); (* append array index to path *)
ELSE
_Path := 'OVERFLOW';
PathOverflow := TRUE;
END_IF
_Element := CONCAT(_Element, '[0]'); (* append array index to path *)
_ArrayIndex[_Level] := 0; (* array index *)

93: (* ']' array end *)
IF LookForValue AND _Value <> '' THEN (* element has been parsed *)
ElementParsed := TRUE;
EXIT; (* exit loop immediately in order to first copy the element details to the output parameters *)
END_IF

IF NOT PathOverflow THEN
StringFound := FINDB(_Path, '[');
IF StringFound > 1 THEN (* remove array index from path string *)
_Path := LEFT(_Path, StringFound - 1);
_Element := LEFT(_Element, FINDB(_Path, '[') - 1);
_Value := '';
_ArrayIndex[_Level] := -1; (* reset array index *)
ELSE (* error: opening square bracket has not been found *)
ERROR := TRUE;
STATUS := 2;
END_IF
END_IF


58: (* ':' key delimiter *)
LookForValue := TRUE;

44: (* ',' element delimiter *)
IF LookForValue AND _Value <> '' THEN (* element has been parsed *)
ElementParsed := TRUE;
EXIT; (* exit loop immediately in order to first copy the element details to the output parameters *)
END_IF

IF RIGHT(_Path, 1) = ']' THEN (* previous element is part of an array *)
IF LEN(LEFT(_Path, FINDB(_Path, '['))) + LEN(INT_TO_STRING(_ArrayIndex[_Level] + 1)) + 1 <= STRING_LENGTH THEN
_ArrayIndex[_Level] := _ArrayIndex[_Level] + 1; (* increment array index *)
_Path := LEFT(_Path, FINDB(_Path, '['));
_Path := CONCAT(_Path, INT_TO_STRING(_ArrayIndex[_Level]));
_Path := CONCAT(_Path, ']');
ELSE
_Path := 'OVERFLOW';
PathOverflow := TRUE;
END_IF
ELSE (* previous element is not part of an array *)
StringFound := FINDB(_Path, '.');
IF StringFound > 1 THEN (* remove last element from path string *)
_Path := LEFT(_Path, StringFound - 1);
ELSE (* previous element was root, empty path variable *)
_Path := '';
END_IF
_Element := '';
_Value := '';
END_IF

34: (* '"' quotation mark *)
IF FirstByte = 0 THEN
FirstByte := CurrentByte + 1;
ELSE
IF NOT LookForValue THEN (* key has been parsed *)
ObjectEmpty := FALSE;
_Element := BUFFER_TO_STRING(PT:=ADR(BUF),SIZE:=STOP_POS + 1,START:=FirstByte,STOP:=CurrentByte - 1);
IF _Path = '' THEN (* path empty, use element as root for path *)
_Path := _Element;
ELSE (* append key to path *)
IF LEN(_Path) + LEN(_Element) + 1 <= STRING_LENGTH THEN
_Path := CONCAT(_Path, '.');
_Path := CONCAT(_Path, _Element);
ELSE
_Path := 'OVERFLOW';
PathOverflow := TRUE;
END_IF
END_IF
ELSE (* value has been parsed *)
_Value := BUFFER_TO_STRING(PT:=ADR(BUF),SIZE:=STOP_POS + 1,START:=FirstByte,STOP:=CurrentByte - 1);
ElementParsed := TRUE;
END_IF
FirstByte := 0;
END_IF

45, 48..57, 46, 110, 117, 108: (* minus, numbers and dot + characters for "null" (not as string but as null value *)
IF LookForValue AND FirstByte = 0 THEN
pValueString := ADR(_Value);
pValueString^[LEN(_Value) + 1] := 0;
pValueString^[LEN(_Value)] := BUF[CurrentByte];
END_IF

END_CASE
CurrentByte := CurrentByte + 1; (* proceed to next byte *)

END_WHILE

IF ElementParsed THEN
ElementParsed := FALSE;
LookForValue := FALSE;
COUNT := COUNT + 1; (* copy output values to interface *)
LEVEL := _Level;
PATH := _Path;
ARRAY_INDEX := _ArrayIndex;
ELEMENT := _Element;
VALUE := _Value;
NEW_DATA := TRUE;
STATUS := 100;
END_IF

IF CurrentByte > STOP_POS THEN (* end of string to be parsed reached *)
DONE := TRUE;
ELSIF WatchdogTimer.Q THEN
STATUS := 101;
END_IF


(* revision history
md 10 Jul 2019 rev 1.0
original version

md 11 Oct 2022 rev 1.1
fixed negative values not being recognized
fixed empty objects breaking path handling
*)


Wie cool wäre es, das über Github machen zu können...