I am using Gemstone/S for various tasks and together with Christian Haider we looked for an example code to insert a jpg-image into a PDF page. This post is a reminder of this message.
The following code reads a jpg file from disc and puts the image on a pdf page.
| jpegFile jpgData aStream soi abort P Y X Nf vm anImageXObject pdfDocument page |
"We get the binary data of the jpg image"
jpegFile := GsFile openReadOnServer: '/home/mf/demo-grafik.jpg'.
jpgData := jpegFile contents.
jpegFile close.
"the first step is to analyse the content of the jpg ... this is example
code !"
aStream := ByteReadStream bigEndianOn: jpgData asByteArray.
soi := aStream next: 2.
(soi first = 255
and: [ soi last = 216 ]) ifFalse:[ self halt: 'not a SOI structure' ].
abort := false.
[ abort ] whileFalse:[
| headerLength frameHeader |
"get header"
frameHeader := aStream next: 2.
(frameHeader first = 255
and: [ frameHeader last >= 192
and: [ frameHeader last <= 255 ]]) ifFalse:[ self halt ].
headerLength := aStream nextUnsignedShort.
frameHeader last = 192
ifTrue:[
"the is the header we want to get"
abort := true.
]
ifFalse:[
"not a header we are interested in"
aStream next: headerLength - 2
]
].
"the stream points to the right header ... now we retrieve the base meta data"
P := aStream next.
Y := aStream nextUnsignedShort.
X := aStream nextUnsignedShort.
Nf := aStream next.
"now to the pdf handling"
"make a dictionary, Valuemap is defined in PDFtalk"
vm := Valuemap new.
vm
at: #Width put: X ;
at: #Height put: Y ;
"can be computed by examine the value of Nf - we assume always the same here"
at: #ColorSpace put: #DeviceRGB;
at: #BitsPerComponent put: P ;
at: #Type put: #XObject ;
at: #Subtype put: #Image.
"Now create a pdf object"
anImageXObject :=
(PDF classAt: #ImageXObject)
on: vm.
anImageXObject
contents: jpgData ;
at: #Filter put: #DCTDecode.
"We create a landscape pdf page"
page := PDF Page
newInBounds: (0 @ 0 corner: 842 @ 595)
colorspace: (PDF classAt: #DeviceRGB) new
render: [:renderer |
"pt unit = 1/72 inch"
renderer isolatedDo: [
renderer
paintImage: anImageXObject
caption: 'Hochrechnung'
in: (34@34 extent: 192 @ 108).
].
].
page saveAndShowAs: 'test.pdf'
This code can be seen as a base for putting jpg graphics into a PDF report.
Thanks to Christian for the small whereby conference to get this code to evolve.
So, heute ist der Bescheid über die Förderung gekommen und auch der genaue Förderbetrag wurde genannt. Dauer der Bearbeitung ca. 4 Monate.
Was einem dabei auffällt – solche Förderung verfolgt immer zwei Punkte:
Förderung des eigentlichen Thema
Förderung des Handwerks
Alles, was selber gekauft wurde (und mit Beleg nachgewiesen wurde: Smart-Regler für die diversen Heizkörper, Netzwerkkabel, Stromzähler für die Wärmepumpe für S0-Signalerzeugung), fiel aus der Förderung raus: Eigenleistung nennt sich das. Die Leistung des Handwerkers – meinen eigenen Stromzähler einzubauen – wird allerdings gefördert.
Baut man also selber das Fundament, dann bekommt man die Rohstoffe nicht gefördert.
Wenn man bedenkt, dass der erste Handwerker die Heizkörper mit 200% Gewinn an mich verkaufen wollte und ich anbot, die Heizkörper selber zu kaufen – die völlig überteuerten Heizkörper werden mit 30% subventioniert – bei Eigenkauf, wird nichts unterstützt.
Egal, beim nächsten Mal also alles auf die Handwerkerrechnung.
Sencha ExtJS benutzt zur Speicherung der State-Information der UI-Komponenten die Instanz Ext.state.Manager. Der bekommt eine Instanz zugewiesen, die drei verschiedene Operationen implementieren muß.
Hier eine Beispielimplementation des StateProvider. Die Daten werden in Objekten – verwaltet durch ein Store – mit den Attributen key und value gespeichert:
/** * Created by mf on 16.12.22. */ Ext.define('Ctm.RemoteStateProvider', { extend: 'Ext.state.Provider', // Der Store muss auf autoSync = false und autoLoad = false definiert sein config: { store: null }, constructor: function (config) { var me = this; Ext.apply(me, config); me.state = {}; me.mixins.observable.constructor.call(me); }, set: function (name, value) { let me = this; let pos, row; if ((pos = me.store.find('key', name)) > -1) { row = me.store.getAt(pos); row.set('value', me.encodeValue(value)); } else { me.store.add({ key: name, value: me.encodeValue(value) }); } if(me.store.isSyncing) return; me.store.sync(); me.fireEvent('statechange', me, name, value); }, get: function(name, defaultValue) { let me = this; let pos, row; if ((pos = me.store.find('key', name)) > -1) { row = me.store.getAt(pos); return me.decodeValue(row.get('value')); } else { return defaultValue; } }, clear: function(name) { let me = this; let pos; if ((pos = this.store.find('name', name)) > -1) { me.store.removeAt(pos); me.store.sync(); me.fireEvent('statechange', this, name, null); } } });
Dazu gehört ein Store, der die Daten in der Gemstone/S speichern soll. Er muß alle 4 CRUD Operationen implementieren. In PUM kann man den Store definieren auf ein DomainObjekt mit den Attributen key und value, die beide eine Zeichenkette speichern sollten. Eine gute Position ist eine 1:n Assoziation von einer Klasse, die den ApplicationUser darstellt.
Diesen Store sollte man in der JS-Anwendung früh definieren und ein load() ausführen. Eine statische Definition in einem ViewModel im ersten Fenster ist zu spät. Der Store muß nach einem erfolgreichem Login erzeugt werden, damit eine korrekte URL durch das Framework erzeugt wird.
uiStateStore = new ctm.store.CTMAPIUIStateValueList();
uiStateStore.load(
function(records, operation, success) {
Ext.state.Manager.setProvider(Ext.create('Ctm.RemoteStateProvider',{
store: uiStateStore
}));
// Nun geht es mit der Anwendung los ...
me.redirectTo("....")
});
Um z.B. ein GRID mit der state-Verwaltung zu beauftragen, kann man ein GRID wie folgt definieren (Attribute stateful und stateId definieren):
Auf der Gemstone-Seite muß man einen Store definieren, eine Domain- und eine API-Klasse und die notwendigen Calls für alle Aktionen. Es folgen Parameter und Rückgabe-Hilfsklassen. Hier eine Beispielimplementierung der vier Methoden unter Gemstone/S:
Dieses Posting dient der Zusammenfassung und Dokumentation – auch weil ich jetzt weiß, wie man in openHab mehrere Informationen gleichzeitig darstellt.
Zuerst der Abgleich der Temperaturen – via Internet für meine Gemeinde gemeldet/hochgerechnet und die Messung durch die WP selber:
Das war eine kalte Woche – nahezu 8 Tage mit Dauerfrost (wenn man den 16.ten rausnimmt) – das könnte der “Putin”sche Winter werden.
Kommen wir zu der zentralen Grafik:
Außentemperatur
Leistung elektrisch gezogen
E-Heizung
Wohnzimmertemperatur
Die Wohnzimmertemperatur (blau) dümpelt so um 20 Grad rum, die kleinen Peaks sind direkter Sonnenschein durch die Glasfront.
Die E-Heizung (gelb) zeigt sich ab -5 Grad im StandBy und schaltet sich dazu (nun weiß ich auch warum – Bivalenzpunkt steht in der Konfiguration mit -5 Grad).
Der Stromverbrauch liegt am 17.ten um und bei 85 kW pro Tag – neue Höchstmarke.
Und nun noch die verschiedenen Temperaturen im System selber:
Außentemperatur
E.Heizung
Kessel
Rücklauf
Sammler
Vorlauf-Mischer
Und nun noch ein Blick auf die Warmwasseraufbereitung:
Ok, die letzten Nächte waren mit bis zu -8 Grad richtig frostig – der Stromverbrauch hat absolute Höchststände erreicht. Hoffe mal, daß das Wetter wieder besser wird.
Heute hat es hier – sehr selten an der Westküste – ordentlich geschneit. Gut und gerne 10cm sind hinzugekommen und der Schnee hat sich auf die Lamellen gelegt. Bevor die schmelzen und festfrieren, habe ich die Lamellen gereinigt.
Am unteren Bereich der Lamellen bildet sich langsam eine feste Eisschicht, die nicht mehr abgetaut wird. Ich muß beim nächsten Tauwetter darauf achten, daß das alles verschwindet …
Wir sind jetzt bei 0 Grad und wieder bei einer Effizienzzahl von 4.0, gestern gab es eine Effizienzzahl von 2.2 bei -8 Grad.
Morgen nacht erwarten wir -12 Grad … das ist ja ein schöner Test. Danach geht es mit den Temeraturen wieder bergauf.
Lange nichts gehört – aber heute sollte man mal wieder ein Posting hinlegen. Wir haben winterliche Temperaturen – und zwar durchaus winterliche Temperaturen mit 7-8 Grad Frost.
Und hier die Stromaufnahme dazu (Aua) …
Was sieht man hier ? Der E-Stab wird zugeschaltet – nicht zu 100%, aber anteilig.
Die Effizienzzahl lag in den letzten Tagen bei 2.8 bis 3, weit entfernt von den 4 bis 5 im Herbst.
Also an den Tagen wie heute gehen gut und gerne 50kw durch den Stromzähler, was €10 pro Tag ausmacht (eon grundversorgung heizstrom).
Das tut zwar weh, aber ich habe gerade meine letzte (in wahrsten Sinne) Gas-Abrechnung bekommen – dort zeigte sich, daß bis zu 60% des gesamten Jahresverbrauches zwischen dem 20.12 und dem 28.02 – also in nur 3 Monaten – verbraucht wurden.
Inzwischen kann ich sogar feststellen, daß die Heizkörper im Hause (in den oberen Etagen) angesprungen sind und fühlbar warm wurden. Ich vermute, daß man dies an den Kesseltemperaturen ablesen kann:
Nun ackert die WP und die Geldzahlungen legen los.
18.11.2022
Wenn ich mal den 18.11. betrachte mit den Temperaturen:
dann sieht man einen Tag mit 0 – 3 Grad. Wobei meine Internetauskunft mit um Mitternacht schon -2 Grad meldete und nicht die 0 Grad, wie die WP selber.
Die Arbeit der WP ist geprägt vom Abtauen. Hier die Stromaufnahme des Gerätes:
Um 13:30 wieder die gewohnte Warmwasserzubereitung. Der Verbrauch an diesem Tag lag bei 40 KW (therm. Energie: 133 KW) bei einer TAZ VT von 3.3. Das sind also beim aktuellen Stromtarif knapp 8€.
Sound ?
Ja, man hört sie. Ein intensives Rauschen gibt sie von sich – ging im Wind von gestern unter – aber nun ist Windstille angesagt und die WP ist eindeutig zu vernehmen.
19.11.2022
Und der nächste Tag wird noch kälter – im Durchschnitt. Verbraucht werden 44 KW bei einer th. Energiemenge von 135KW und einen TAV VT von 3.1.
Temperatur
Leistungsaufnahme (KW/h)
23.11.2022
So, die Kälte läßt nach. 24 el.KW und 93 th.KW bei 3.9:
Hier die Temperaturen vom 23.11 bis in den 24.11
und hier die Leistungsaufnahme im gleuchen Zeitrau, die zeigt, wie sich die WP langsam wieder beruhigt:
Die WP arbeitet wieder auf der geringsten Modulationsstufe.
Also Fazit für mich: bei einer Temperatur von 4 bis 5 Grad beginnt die “Gefahr” der Vereisung der WP-Lamellen. Dann sinkt die TAV VT auf bis zu 3 ab.
Die WP hat sich dann alle 1.5 bis 2.5 Stunden enteist, in den oberen Grafiken kann man bis zu 10 Peeks ablesen.
Blätter
Ach ja, diese Blätter von den Bäumen – bei uns sind viele Blätter, denn im Gegensatz zu unseren nachbarn, haben wir alle Bäume behalten und versuchen nichts zu fällen.
Man soll ja den Luftaustritt der WP nicht in die Hauptwindrichtung ausrichten, also hatten wir die WP gedreht (auch damit der Austritt nicht direkt zum Nachbarn zeigt)- der Austritt zeigt nach Norden – aber nun pustet der Wind hinten rein … und bringt die Blätter mit. Das Schutzgitter soll die Lamellen der WP eher vor groben Sachen schützen – sicherlich nicht vor Blättern. Also müssen wir die Lamellen bei Laubfall immer wieder von den Blättern reinigen.
Der Winter hat meine Wärmepumpe “Wolfi” erreicht. Anders kann man es nicht sagen. Seit gestern also feuchtes, kaltes Wetter mit regelmäßigem Niederschlag.
Das Heizprogramm ist nun für den gesamten Tag aktiviert und “Wolfi” muß richtig arbeiten …
Zuerst einmal muß man sagen, daß die Temperaturen noch oberhalb von 0 Grad liegen:
Und es lag ein regelmäßiger Wind aus östlicher Richtung vor und ab Nachmittag sehr feucht.
Das führte nun dazu, daß die Heizung nun regelmäßig in der Nacht enteisen muß:
Ich gehe mal davon aus, daß die Peaks in der Nacht Enteisungsvorgänge sind (einen habe ich mir sogar angeschaut, um das mal gesehen zu haben). Und der Stromverbrauch ist hochgegangen. Gestern wurden 31 kw (127 thermische kw erzeugt) verbraucht bei einer TAZ VT von 4.1.
Die folgende Grafik zeigt den Strombedarf über den gesamten Tag ( 17 .. 18) und die Grafik zeigt, daß die WP den gesamten Tag aktiv war:
We had yesterday a small video session using whereby and some Smalltalkers diskussed the topic “totp” as second authentification method after an successful login (we were VASmalltalk, VisualWorks and Gemstone related).
To get all work done under Gemstone you need the MSKLibQREncode, the Multibase-Code and one class from the MSK-ModelBaseRuntime package: MSKTOTPSupport.
The MSKTOTPSupport class has three class methods with all stuff needed. Perhaps some methods are defined elsewhere, but you should at least get the ideaa …
totpCurrentValueForSecret: keyArray forTime: aDateAndTime digits: numberOfDigits period: seconds algorithm: aString ” Returns a new value or nil in error case
I bought an new laptop – I mean really a “new” laptop. I decided to buy this time a new laptop with preinstalled, encrypted Linux operating system Tuxedo OS 1 (based on Ubuntu 22.04) and I’ve chosen the Tuxedo Pulse 15 Gen2.
General Description
You may use the link above to get more technical information about this laptop. In this posting I only mention some informations which seem to be perhaps not mentioned somewhere and are important for me.
In the past I have used several other machines – the Thinkpad W530 (the last classical Thinpad machine from Lenovo with good quality):
Then the 17” ZBook17, Gen2 from HP – dated a little bit later than the W530 – but with lots of room inside. But a very heavy laptop (around 3.x kg), coming into age and when working – getting louder and louder now.
Then at the beginning of this year I bought a newer machine – the Huawei Matebook 16 (AMD CPU pretty similar to the Pulse machine) – and used it in a dual boot configuration for Windows and Linux:
The Matebook has much more power than the older machines – and I installed Ubuntu 22.04 LTS on that machine. The keyboard is not that good as on the older machines and has some quality problems. The left shift key is sometimes not working very well. The dual boot options is making problems with new versions of the kernel and VirtualBox under Ubuntu. I’ve to sign the Ubuntu VirtualBox files again and again to be able to start the VirtualBox. No sound under Linux, no background light of the keyboard … and no rj45 tcpip network port …
The machine has only 16 GB RAM and this is a main limiting point under Linux when doing development in the area I am working with. I assumed, that it would be ok, but I hit that limitation several times … and of course the builtin SSD with a size of 512GByte is also limiting. So I added an external hub to get access to external harddisc drives, I added a new power supply (based on USB-C) to feed the hub and the additional drives. That became a cable mess …. and at one working event, I forgot an external SSD where some badly needed files were located on :-(.
So I looked for a new machine and the Matebook will become a Windows only machine now …
So I looked for a development machine with more RAM, more harddisc space and not as heavy as the ZBook17 I mentioned earlier.
The picture below show from top to buttom: Tuxedo, Matebook, Lenovo W530 and ZBook 17
And I wanted to have no problems with Linux and for the first time I decided to build a new, linux only laptop. I ordered it from the Tuxedo web-page and added additional RAM (now 64 GB) and harddisc space (now 4TB).
Ordering and Delivering
The laptop arrived around 10 days after I ordered it and it was well packaged and delivered to me. Actually I was surprised to get it delivered at that day – no information was sent to me, that I should prepare myself for the post man … I got that eMail notification two days later after arrival of the laptop. DHL seems to be very fast this time 🙂
Screen
The screen has a higher resolution than the ZBook or the Matebook – and normally this would be not useful for my eyes – but at 125% with KDE most of the tools can be used quite nice.
The screen is bright enough for me, the quality is good and I like the display.
Connectivity
The system has an additional HDMI port (which I use for a 4K display), the RJ45 network port and two fast USB port (the Matebook has also USB ports, but only slow ones) and one USB-C port. Perhaps useful may also the 3.5 sound port for external boxes.
Keyboard
The keyboard has the quality of the ZBook17, Gen2 keyboard I had used for some time in the past (which had the best keyboard I have ever worked with, even better than the Lenovo W530 I also used) and it is far better than the Matebook16 system. Yes, there is no numpad – but for a 15” laptop this is ok. The keys have the correct sizes for me and typing can be done pretty fast.
Strange for me is, that to press F12 (debugger tool in browsers) I have to press Fn and F12 to get there … normally I simply pressed F12 – but on this machine the laptop goes into the standby mode. I will learn that …
When I touch the keyboard the backlit light of the keyboard is going on and that is working under Linux. I never got this working with the Huawei Matebook 16.
Sound
It is working under Linux, out of the box. The quality is not that good and the speaker are located on the bottom side of the laptop. The Matebook 16 is much better in this area (under Windows), but the Matebook16 system is not yet supported under Ubuntu 22.04.
Fan Noise
The laptop is a pretty silent machine … but if you get an average load of about 6 over some time you will hear the machine. Some java programs will help you to find out … its not getting very much loader if you have a load of 6 or of 10.
The fan manages to cool the system down while the fan is running at around 60% and the system seems to be stable running at 3 Ghz. That are good news.
WebCam
A webcam is build into the system, just above the screen (and not as done at the MateBook in the keyboard ….). It is working, the quality is not so good – but for me totally ok.
Operating System
The OS behaves like an Ubuntu 22.04, but with a much nicer UI. During installation (or better final configuration) I was not able to enable the WLAN support to upgrade the system to the latest system level. After the installation this worked of course, so I made an update after that.
Conclusion
The system is working out of the box, has an up to date operating system, the UI looks pretty nice, is quite powerful with up to 16 threads, can be configured with up to 64 GB of RAM and both NVM SSDs are very fast. The screen has a very good quality … and its weight is around 1.5 kg.
Connections
The pictures show all possible connectors on the left and right of the computer:
So, that’s it for now … back to the computer and having fun.