2525*/
2626
2727import GObject from 'gi://GObject' ;
28+ import Gio from 'gi://Gio' ;
29+ import GLib from 'gi://GLib' ;
2830import * as SubProcessModule from './helpers/subprocess.js' ;
2931import * as FileModule from './helpers/file.js' ;
3032import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js' ;
@@ -120,6 +122,12 @@ export const Sensors = GObject.registerClass({
120122 for ( let label in this . _tempVoltFanSensors [ type ] ) {
121123 let sensor = this . _tempVoltFanSensors [ type ] [ label ] ;
122124
125+ // Special handling for Aquacomputer Vision
126+ if ( sensor . aquacomputer ) {
127+ this . _readAquacomputerSensor ( callback , label , sensor , type ) ;
128+ continue ;
129+ }
130+
123131 new FileModule . File ( sensor [ 'path' ] ) . read ( ) . then ( value => {
124132 this . _returnValue ( callback , label , value , type , sensor [ 'format' ] ) ;
125133 } ) . catch ( err => {
@@ -128,6 +136,48 @@ export const Sensors = GObject.registerClass({
128136 }
129137 }
130138
139+ _readAquacomputerSensor ( callback , label , sensor , type ) {
140+ try {
141+ let file = Gio . File . new_for_path ( sensor [ 'path' ] ) ;
142+ file . read_async ( GLib . PRIORITY_DEFAULT , null , ( obj , res ) => {
143+ try {
144+ let stream = obj . read_finish ( res ) ;
145+ let input = new Gio . DataInputStream ( { base_stream : stream } ) ;
146+
147+ input . read_bytes_async (
148+ 64 ,
149+ GLib . PRIORITY_DEFAULT ,
150+ null ,
151+ ( input , res2 ) => {
152+ try {
153+ let bytes = input . read_bytes_finish ( res2 ) ;
154+ let arr = new Uint8Array ( bytes . get_data ( ) ) ;
155+
156+ if ( arr . length < 64 || arr [ 0 ] !== 0x01 ) {
157+ this . _returnValue ( callback , label , 'disabled' , type , sensor [ 'format' ] ) ;
158+ return ;
159+ }
160+
161+ // Read coolant temperature
162+ const offset = 0x0037 + 1 ;
163+ let raw = arr [ offset ] | ( arr [ offset + 1 ] << 8 ) ;
164+ let temp = ( raw / 100 ) * 1000 ; // millidegrees
165+
166+ this . _returnValue ( callback , label , temp , type , sensor [ 'format' ] ) ;
167+ } catch ( e ) {
168+ this . _returnValue ( callback , label , 'disabled' , type , sensor [ 'format' ] ) ;
169+ }
170+ }
171+ ) ;
172+ } catch ( e ) {
173+ this . _returnValue ( callback , label , 'disabled' , type , sensor [ 'format' ] ) ;
174+ }
175+ } ) ;
176+ } catch ( e ) {
177+ this . _returnValue ( callback , label , 'disabled' , type , sensor [ 'format' ] ) ;
178+ }
179+ }
180+
131181 _queryMemory ( callback ) {
132182 // check memory info
133183 new FileModule . File ( '/proc/meminfo' ) . read ( ) . then ( lines => {
@@ -801,6 +851,62 @@ export const Sensors = GObject.registerClass({
801851 // Launch nvidia-smi subprocess if nvidia querying is enabled
802852 this . _reconfigureNvidiaSmiProcess ( ) ;
803853 this . _discoverGpuDrm ( ) ;
854+
855+ // Aquacomputer Next Vision
856+ const VENDOR_ID = '0c70' ;
857+ const PRODUCT_ID = 'f00c' ;
858+
859+ let base = '/sys/class/hidraw/' ;
860+ let dir = Gio . File . new_for_path ( base ) ;
861+ try {
862+ let enumerator = dir . enumerate_children (
863+ 'standard::*' ,
864+ Gio . FileQueryInfoFlags . NONE ,
865+ null
866+ ) ;
867+ let info ;
868+ while ( ( info = enumerator . next_file ( null ) ) !== null ) {
869+ let name = info . get_name ( ) ; // e.g. hidraw7
870+ let deviceSymlink = `${ base } ${ name } /device` ;
871+ let realDevicePath = GLib . file_read_link ( deviceSymlink ) ;
872+ // realDevicePath will be something like:
873+ // ../../devices/.../0003:0C70:F00C.0008
874+ let parts = realDevicePath . split ( '/' ) ;
875+ let devDir = parts [ parts . length - 1 ] ;
876+ // devDir is like "0003:0C70:F00C.0008"
877+ let match = devDir . match (
878+ / ^ [ 0 - 9 A - F a - f ] + : ( [ 0 - 9 A - F a - f ] { 4 } ) : ( [ 0 - 9 A - F a - f ] { 4 } ) \. /
879+ ) ;
880+ if ( match ) {
881+ let vid = match [ 1 ] . toLowerCase ( ) ;
882+ let pid = match [ 2 ] . toLowerCase ( ) ;
883+ if ( vid === VENDOR_ID && pid === PRODUCT_ID ) {
884+ // Check if AC Vision sensor already exists to prevent re-adding
885+ if ( ! ( 'Coolant Temp' in this . _tempVoltFanSensors [ 'temperature' ] ) ) {
886+ this . _addTempVoltFan (
887+ null , // Don't call callback during discovery
888+ {
889+ type : 'temperature' ,
890+ format : 'temp' ,
891+ input : `/dev/${ name } ` ,
892+ aquacomputer : true ,
893+ } ,
894+ 'AC Vision' ,
895+ 'Coolant Temp' ,
896+ '' ,
897+ 0 // placeholder value, will be read during query
898+ ) ;
899+ }
900+ break ;
901+ }
902+ } else {
903+ }
904+ }
905+ enumerator . close ( null ) ;
906+ } catch ( e ) {
907+ // If the hidraw device is not available, we just ignore it.
908+ // This can happen if the device is not connected or if the user does not have permission to access it.
909+ }
804910 }
805911
806912 _discoverGpuDrm ( ) {
@@ -955,6 +1061,12 @@ export const Sensors = GObject.registerClass({
9551061 if ( label == 'iwlwifi_1 temp1' ) label = 'Wireless Adapter' ;
9561062 if ( label == 'Package id 0' ) label = 'Processor 0' ;
9571063 if ( label == 'Package id 1' ) label = 'Processor 1' ;
1064+ if ( label == 'nct6799 fan1' ) label = 'VRM HeatSink Fan' ;
1065+ if ( label == 'nct6799 fan2' ) label = 'Radiator Fan(s)' ;
1066+ if ( label == 'nct6799 fan6' ) label = 'Chipset/NVMe Fan' ;
1067+ if ( label == 'nct6799 fan7' ) label = 'AIO Pump' ;
1068+ if ( label == 'nct6799 SYSTIN' ) label = 'Motherboard Temp' ;
1069+ if ( label == 'nct6799 CPUTIN' ) label = 'CPU Socket Temp' ;
9581070 label = label . replace ( 'Package id' , 'CPU' ) ;
9591071
9601072 let types = [ 'temperature' , 'voltage' , 'fan' ] ;
@@ -974,12 +1086,15 @@ export const Sensors = GObject.registerClass({
9741086 }
9751087 }
9761088
1089+ if ( ! obj [ 'aquacomputer' ] && callback ) {
9771090 // update screen on initial build to prevent delay on update
9781091 this . _returnValue ( callback , label , value , obj [ 'type' ] , obj [ 'format' ] ) ;
1092+ }
9791093
9801094 this . _tempVoltFanSensors [ obj [ 'type' ] ] [ label ] = {
9811095 'format' : obj [ 'format' ] ,
982- 'path' : obj [ 'input' ]
1096+ 'path' : obj [ 'input' ] ,
1097+ 'aquacomputer' : obj [ 'aquacomputer' ] || false ,
9831098 } ;
9841099 }
9851100
0 commit comments