Ja, Du hast da ein paar Fehler drin.
Zum ersten, wenn Du auf den Status eines Items zugreifen willst, musst Du das Wort .state anhängen.
Zum zweiten, ein Status ist ein Status. Du brauchst aber eine Zahl, also musst Du ein Type Casting verwenden.
Zum dritten, wenn openHAB startet, enthält das Item keine gültige Zahl, das musst Du berücksichtigen.
Zum vierten kann es sein, das die Rule auch triggert, wenn Du nichts gedruckt hast, weil officejet_totalcount erstmalig einen Wert zugewiesen bekommt.
Deine Rule müsste also eher so aussehen:
Code: Alles auswählen
rule "Druckseite add"
when
Item officejet_totalcount changed
then
if(!(previousState instanceof Number) return; // das Item wurde gerade initialisiert, Rule abbrechen
if(!(officejet_monthcount.state instanceof Number)) {
officejet_monthcount.postUpdate(0) // einmalig initialisieren
Thread::sleep(300) // und openHAB etwas Zeit geben
}
officejet_monthcount.postUpdate((officejet_monthcount.state as Number) + 1)
end
Es bietet sich an, das Item zu persistieren, schon um beim Start von openHAB den letzen gültigen Wert zu erhalten.
Allerdings bin ich mir nicht sicher, ob officejet_totalcount wirklich immer nur um 1 anwächst. Es wäre also vermutlich besser, die Differenz zwischen dem alten und dem neuen totalcount zu nutzen:
Code: Alles auswählen
officejet_monthcount.postUpdate((officejet_monthcount.state as Number) + (officejet_totalcount.state as Number) - (previousState as Number))
Noch besser wäre es vermutlich, totalcount zu persistieren (z.B. mit rrd4j) und in der Rule die Differenz zum letzen 18. zu bestimmen, also in etwa so:
Code: Alles auswählen
rule "Druckseite add"
when
System started or // Systemstart, Anzeige mit aktuellem Wert initialisieren
Item officejet_totalcount changed
then
val nDay = now.minusMonths(if(now.getDayOfMonth < 18) 1 else 0).minusDays(now.minusMonths(if(now.getDayOfMonth < 18) 1 else 0).getDayOfMonth).plusDays(18).timeAtStartOfDay
officejet_monthcount.postUpdate((officejet_totalcount.state as Number) - (officejet_totalcount.historicState(nDay).state as Number)
end
nDay ist dabei der letzte 18., Mitternacht. der Ausdruck sieht ziemlich krude aus

, weshalb ich ihn noch mal auseinander nehmen möchte:
Code: Alles auswählen
val nDay = now //Jetzt
.minusMonths( //Minus Monate
if(now.getDayOfMonth < 18) 1 else 0 // falls vor dem 18. 1 sonst 0
).minusDays( //Minus Tage
now.minusMonths(if(now.getDayOfMonth < 18) 1 else 0) // siehe voriger Ausdruck
.getDayOfMonth) // aktueller Tag (oder der aktuelle Tag des Vormonats, das ergibt also den letzten Tag des Vormonats oder Vor-Vormonats)
.plusDays(18) // Zähle 18 Tage hinzu (also der 18. des aktuellen Monats oder des Vormonats)
.timeAtStartOfDay // Nimm Mitternacht als Zeitpunkt
Dieser Ausdruck sollte also immer den Beginn des Abrechnungszeitraums liefern. Falls der Zeitpunkt eher 1 Uhr sein soll, müsste man noch ein .plusHours(1) ran hängen. Der Punkt ist, dass es mit dieser Berechnung keine Rolle spielt, ob wir ein Schaltjahr haben oder eine Jahresgrenze überschreiten, vor oder nach dem 18 des Monats sind, der Monat 28, 29, 30 oder 31 Tage hat.
Damit wäre dann die zweite Rule auch obsolet. Die zweite Rule hat ansonsten auch noch einen Fehler, denn Time cron arbeitet sekundengenau (das ist quartz cron, nicht das gewohnte Tool in GNU/Linux oder anderen unixoiden Umgebungen)
Dein Ausdruck
bedeutet also: um 18:01:00, täglich. Was Du vermutlich eher wolltest, war das hier:
bedeutet: um 01:00:00, am 18. jeden Monats.
Da die Rule Persistence nutzt, wird sie erst nach dem ersten 18. funktionieren, der schon persistiert wurde.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet