single-task message and cursor pin S on X

Recently i find many session are waiting for Event <cursor pin s on x> in my customer's AIX 10.2.0.4 instance, it's a new event in the 10gr2,after mutex take  place of latch . When a session is going to parse or reparse one cursor, need to pin X this cursor first. Then the others who what to execute this child cursor  have to wait until pin X released. I looked for the session who was pining that cursor on  X mode ,and saw it was waiting on event single-task messag: the mutex idn is d322e445,and operated in EXCL mode; It correspond to the cursor whose hash is "ff2c2fd459ac5ee188586781d322e445" as after:
PROCESS 1753:
----------------------------------------
SO: 70000048e9d5e68, type: 2, owner: 0, flag: INIT/-/-/0x00
(process) Oracle pid=1753, calls cur/top: 70000043308cb08/70000043798a6e0, flag: (0) -
int error: 0, call error: 0, sess error: 0, txn error 0
(post info) last post received: 109 0 4
last post received-location: kslpsr
last process to post me: 70000048f8deaf0 1 6
last post sent: 0 0 24
last post sent-location: ksasnd
last process posted by me: 70000048f8deaf0 1 6
(latch info) wait_event=0 bits=0
Process Group: DEFAULT, pseudo proc: 70000048ca877c0
O/S info: user: orauser, term: UNKNOWN, ospid: 3318124
OSD pid info: Unix process pid: 3318124, image: oracle@p595crm1
.........................
----------------------------------------
SO: 70000048eed0d30, type: 4, owner: 70000048e9d5e68, flag: INIT/-/-/0x00
(session) sid: 3311 trans: 70000046be86948, creator: 70000048e9d5e68, flag: (100041) USR/- BSY/-/-/-/-/-
DID: 0001-06D9-008347C7, short-term DID: 0001-06D9-008347C8
txn branch: 70000046a261488
oct: 3, prv: 0, sql: 700000414e4f570, psql: 700000415f47a90, user: 50/SHUCRM1C
service name: CRMDB1
O/S info: user: pausr12, term: unknown, ospid: 1234, machine: p570web2
program: JDBC Thin Client
application name: JDBC Thin Client, hash value=2546894660
waiting for 'single-task message' blocking sess=0x0 seq=22963 wait_time=0 seconds since wait started=6
=0, =0, =0
Dumping Session Wait History
for 'SQL*Net message from dblink' count=1 wait_time=325
driver id=54435000, #bytes=1, =0
for 'SQL*Net message to dblink' count=1 wait_time=2
driver id=54435000, #bytes=1, =0
for 'SQL*Net message from dblink' count=1 wait_time=383
driver id=54435000, #bytes=1, =0
for 'SQL*Net message to dblink' count=1 wait_time=1
driver id=54435000, #bytes=1, =0
for 'SQL*Net message from dblink' count=1 wait_time=265
driver id=54435000, #bytes=1, =0
for 'SQL*Net message to dblink' count=1 wait_time=2
driver id=54435000, #bytes=1, =0
for 'SQL*Net message from dblink' count=1 wait_time=677
driver id=54435000, #bytes=1, =0
for 'SQL*Net message to dblink' count=1 wait_time=0
driver id=54435000, #bytes=1, =0
for 'SQL*Net message from dblink' count=1 wait_time=237
driver id=54435000, #bytes=1, =0
for 'SQL*Net message to dblink' count=1 wait_time=1
driver id=54435000, #bytes=1, =0
temporary object counter: 0
SO:  70000043e695968, type: 53, owner: 70000048eed0d30, flag: INIT/-/-/0x00
LIBRARY OBJECT LOCK: lock=70000043e695968 handle=700000410dd46c8 mode=N                           --the child cursor
call pin=0 session pin=0 hpc=0000 hlc=0000
htl=70000043e6959e8[70000041e9eb830,70000042411c178] htb=70000042411c178  ssga=70000042411bc10
user=70000048eed0d30 session=70000048eed0d30 count=1 flags=CBK[0020]  savepoint=0x0
LIBRARY OBJECT HANDLE: handle=700000410dd46c8 mtx=700000410dd47f8(0)  cdp=0
namespace=CRSR flags=RON/KGHP/PN0/EXP/[10010100]
kkkk-dddd-llll=0000-0001-0001  lock=N pin=X latch#=23 hpc=fffc  hlc=fffc                                     --lock  in NULL mode,pin on X mode
lwt=700000410dd4770[700000410dd4770,700000410dd4770]  ltm=700000410dd4780[700000445169a08,700000453b69228]
pwt=700000410dd4738[700000410dd4738,700000410dd4738]  ptm=700000410dd4748[700000410dd4748,700000410dd4748]
ref=700000410dd47a0[70000043d1b5e58,70000043d1b5e58]  lnd=700000410dd47b8[700000410dd47b8,700000410dd47b8]
LIBRARY OBJECT: object=7000004354983b0
type=CRSR flags=EXS[0001] pflags=[0000] status=VALD load=0
DEPENDENCIES: count=4 size=16
TRANSLATIONS: count=2 size=16
DATA BLOCKS:
data#     heap  pointer    status pins change whr
----- -------- -------- --------- ---- ------ ---
0 7000004359e4768 7000004354984c8 I/P/A/-/-    0 NONE   00
6 700000414b0e4d0 700000450c0bc28 I/P/A/-/E    0 NONE   00

----------------------------------------

KGX Atomic  Operation Log 70000041853c068
Mutex 700000414b0e3d8(3311, 0) idn d322e445 oper EXCL
Cursor Pin uid 3311 efd 0 whr 1 slp  0      -- pin sid 3311
opr=3 pso=70000043e695968  flg=0            -- operate code is 3
pcs=700000414b0e3d8 nxt=0 flg=35 cld=0 hd=700000410dd46c8   par=70000041d78b1e0    -- child cursor handle address is 700000410dd46c8
ct=0 hsh=0 unp=0 unn=0 hvl=1d78b4b8 nhv=1  ses=70000048eed0d30                              -- heap 0 pointer address 70000041d78b1e0
hep=700000414b0e458 flg=80 ld=1 ob=7000004354983b0 ptr=700000450c0bc28  fex=700000450c0af38
----------------------------------------
SO: 70000041e9eb7b0, type: 53, owner: 70000048eed0d30, flag:  INIT/-/-/0x00
LIBRARY OBJECT LOCK: lock=70000041e9eb7b0 handle=700000414e4f570 mode=N
call pin=0 session pin=0 hpc=0000 hlc=0000
htl=70000041e9eb830[70000044590d030,70000043e6959e8] htb=70000042411c178  ssga=70000042411bc10
user=70000048eed0d30 session=70000048eed0d30 count=1 flags=[0000]  savepoint=0x4c08a856
LIBRARY OBJECT HANDLE: handle=700000414e4f570 mtx=700000414e4f6a0(0)  cdp=1
name=
SELECT * FROM(SELECT A.*, rownum r FROM( select  account_id,billing_nbr,calling_nbr,called_nbr,to_date,call_duration,charge_item_name,to_char(rate  /100, '99999999999990.99') rate, charge,channel_id from ct_05
where  1=1 and account_id ='300187744'  and key_source_type ='52001'  order by to_date ) A WHERE rownum <= 15 ) B WHERE r > 0
hash=ff2c2fd459ac5ee188586781d322e445 timestamp=06-04-2010 15:14:33
namespace=CRSR flags=RON/KGHP/TIM/PN0/MED/DBN/[50010040]
kkkk-dddd-llll=0000-0001-0001 lock=N pin=0 latch#=23 hpc=0018 hlc=0018
lwt=700000414e4f618[700000414e4f618,700000414e4f618]  ltm=700000414e4f628[700000414e4f628,700000414e4f628]
pwt=700000414e4f5e0[700000414e4f5e0,700000414e4f5e0]  ptm=700000414e4f5f0[700000414e4f5f0,700000414e4f5f0]
ref=700000414e4f648[700000414e4f648,700000414e4f648]  lnd=700000414e4f660[700000414e4f660,700000414e4f660]
LIBRARY OBJECT: object=70000041d78b0c8
type=CRSR flags=EXS[0001] pflags=[0000] status=VALD load=0
CHILDREN: size=16
child#    table reference   handle
------ -------- --------- --------
0 70000043d1b61e8 70000043d1b5e58 700000410dd46c8                                 -- the child cursor
DATA BLOCKS:
data#     heap  pointer    status pins change whr
----- -------- -------- --------- ---- ------ ---
0 7000004467f6078 70000041d78b1e0  I/P/A/-/-    0 NONE   00                                      --  heap 0
The session is active,and its wait history indicates there are some dblink operation inside the running SQL, When this session waited to reparse the only child cursor for that SQL , it pin this child cursor in X mode first,and then it need more information from remote DB , but no response until SQL*NET MESSAGE from DBLINK timeout,it was waiting single-task message for more than 6 seconds when tracing. In this scenario other sessions who wait to execute this child cursor were all waiting , so sadly. The oracle document describes <single-task message> as When running single task, this event indicates that the session waits for the client side of the executable. A little odd,the blocked also did some single task when it lost one dblink connection. I searched the metalink with keyword: single-task message, there were few documents  found , but fortunately below note:
Hdr: 7757687 10.2.0.3.0 RDBMS 10.2.0.3.0 PRG INT/DISTR PRODID-5 PORTID-212 Abstract: CURSOR: PIN S WAIT ON X BLOCKER "SINGLE-TASK MESSAGE" PROBLEM: -------- The databse has multiple processes waiting on "CURSOR: PIN S WAIT ON X" The holder of the mutes is waiitng on "single-task message" form almost 745687 seconds. The query run by the holder  does conatin a dblink. DIAGNOSTIC ANALYSIS: -------------------- All the  process waiting on the same mutex:- waiting for 'cursor: pin S wait on X' blocking sess=0x0 idn=5d779f21, value=7af00000000, where|sleeps=57a0dfdb6 Holder PROCESS 26: KGX Atomic Operation Log 700000061490300 Mutex 70000006226e0f0(1967, 0) idn 5d779f21 oper EXCL Cursor Pin uid 1967 efd 0 whr 1 slp 0 opr=3 pso=7000000670f93a0 flg=0 pcs=70000006226e0f0 nxt=0 flg=35 cld=0 hd=7000000606838f0 par=7000000629006a8 ct=0 hsh=0 unp=0 unn=0 hvl=62900980 nhv=1 ses=700000079543fe0 hep=70000006226e170 flg=80 ld=1 ob=700000062fe69a8 ptr=700000065f124f8 fex=700000065f11808 Session object for this process:- SO: 700000079543fe0, type: 4, owner: 70000007a6ad538, flag: INIT/-/-/0x00 (session) sid: 1967 trans: 0, creator: 70000007a6ad538, flag: (41) USR/- BSY/-/-/-/-/- DID: 0001-001A-00000A38, short-term DID: 0001-001A-00000A39 txn branch: 0 oct: 3, prv: 0, sql: 700000062900e18, psql: 70000005d797bc8, user: 21/V500 O/S info: user: d_c11, term: , ospid: 6271140, machine: aruput5 program: cpm_srvscript@aruput5 (TNS V1-V3) application name: cpm_srvscript@aruput5 (TNS V1-V3), hash value=0 waiting for 'single-task message' blocking sess=0x0 seq=7071 wait_time=0 seconds since wait started=745687
This bug which occurs on Version 10.2.0.3 is so similar to my case on AIX version 10.2.0.4, so as the stack trace: ksdxfstk+002c<-ksdxcb+04e4<-sspuser+0074<-000044C0<-nttrd+0120<-nsprecv+07a0<- nscon+0218<-nsdo+157c<-nscall3+012c<-nscall+0778<-niotns+0888<-nigcall+0028<-osnco n+0540<-kpkiadef+006c<-upiini+03fc<-upiah0+00ac<-kpuatch+0808<-OCIServerAttach+011 4<-kpnconn+02a4<-npicon0+042c<-kpndbcon+0630<-OCIKDBLinkConn2+0038<-OCIKDBLinkConn +002c<-ddfnet2Normal+011c<-kkmfcbrm+009c<-kkmpfcbk+02a0<-qcsprfro+0538<-qcsprfro_tree +0318<-qcsprfro_tree+01c8<-qcspafq+0068<-qcspqb+0470<-kkmdrv+003c<-opiSem+13b4<-opiDe ferredSem+0234<-opitca+01e8<-kksFullTypeCheck+001c<-rpiswu2+034c<-kksLoadChild+30b0<- kxsGetRuntimeLock+0810<-kksfbc+2930<-kkspsc0+0ffc<-kksParseCursor+00d4<-opiosq0+0b30< -kpooprx+0168<-kpoal8+0400<-opiodr+0adc<-ttcpip+1020<-opitsk+10b0<-opiino+0990<-opiod r+0adc<-opidrv+0474<-sou2o+0090<-opimai_real+01bc<-main+0098<-__start+0098 My case stack trace: ksdxfstk+002c<-ksdxcb+04e4<-sspuser+0074<-000044C0<-nttcni+01b8<-nttcon+04f4<-ntconn+0160< -nsopen+0960<-nscall1+01b0<-nscall+049c<-niotns+0880<-nigcall+0028<-osncon+0540<-kpkiadef+006c< -upiini+0408<-upiah0+00ac<-kpuatch+0808<-OCIServerAttach+0114<-kpnconn+02a4<-npicon0+042c< -kpndbcon+0630<-OCIKDBLinkConn2+0038<-OCIKDBLinkConn+002c<-ddfnet2Normal+011c<-kkmfcbrm+009c< -kkmpfcbk+02a0<-qcsprfro+0538<-qcsprfro_tree+03f0<-qcsprfro_tree+0228<-qcspafq+0068< -qcspqbDescendents+03a0<-qcspqb+00ac<-qcsevw+02e0<-kkmevw+0a58<-kkmfcbvw+0178< -kkmfcblo+0e38<-kkmpfcbk+0250<-qcsprfro+0538<-qcsprfro_tree+03f0<-qcsprfro_tree+0228< -qcspafq+0068<-qcspqbDescendents+03a0<-qcspqb+00ac<-qcsevw+02e0<-qcsfpsq+003c< -kkmfcbsq+01e8<-kkmpfcbk+0260<-qcsprfro+0538<-qcsprfro_tree+03f0<-qcsprfro_tree+0228< -qcspafq+0068<-qcspqbDescendents+03a0<-qcspqb+00ac<-qcsevw+02e0<-qcsfpsq+003c< -kkmfcbsq+01e8<-kkmpfcbk+0260<-qcsprfro+0538<-qcsprfro_tree+03f0<-qcsprfro_tree+0228< -qcspafq+0068<-qcspqbDescendents+03a0<-qcspqb+00ac<-kkmdrv+003c<-opiSem+13c0< -opiprs+01ac<-kksParseChildCursor+05e0<-rpiswu2+034c<-kksLoadChild+1d88< -kxsGetRuntimeLock+0810<-kksfbc+28b0<-kkspsc0+0ffc<-kksParseCursor+00d4<-opiosq0+0ae0< -kpooprx+0168<-kpoal8+0400<-opiodr+0ae0<-ttcpip+1020<-opitsk+1124<-opiino+0990<-opiodr+0ae0< -opidrv+0484<-sou2o+0090<-opimai_real+01bc<-main+0098<-__start+0098 Both of them have called OCIKDBLinkConn->OCIKDBLinkConn2->kpndbcon->npicon0->kpnconn->OCIServerAttach->kpuatch and follow. Till now this bug has no patch to apply or workaround way what's awful. As "Bug 5111335: STREAMS PROPAGATION STUCK ON "SINGLE-TASK MESSAGE" PRODUCE LIBRARY CACHE LOCK CO" described:
Hdr: 5111335 10.2.0.2 RDBMS 10.2.0.2 STREAMS PRODID-5 PORTID-226 Abstract: STREAMS PROPAGATION STUCK ON "SINGLE-TASK MESSAGE" PRODUCE LIBRARY CACHE LOCK CO This is a three cluster environment. Two nodes per cluster and on that cluster running RAC with 2 instances. The databases involved are: GCTGCMU is the "GCT" database in GCM = Greenwich USA, will be named USA from now on GCTHKGU is the "GCT" database in HKG = Hong Kong, will be named HKG from now on GCTLONU is the "GCT" database in LON = London, will be named LON from now on On this environment there is a Streams bi-directional replication environment defined between the 3 databases. USA database is propagating changes captured to LON and HKG. There are two propagations defined from this site to every site. 4 propagations as a total. GCTHKGU_BATCH_PROPAGATE GCTLONU_BATCH_PROPAGATE GCTHKGU_DAILY_PROPAGATE GCTLONU_DAILY_PROPAGATE Daily propagation propagates changes stored on streams queue STRMADMIN.STREAMSOUT_DAILY. Batch propagation propagates changes stored on streams queue STRMADMIN.STREAMSOUT_BATCH This databases have been upgraded to 10.2.0.2 from 10.2.0.1 last 13-Mar-2006, and no problems were reported. Customer reported that he could see that propagations from USA to HKG were stucked on library cache lock. This situation was solved by customer by bouncing USA instances. Analyzing the systemstate dumps we could see that there were propagations locked on this situation and QMON slaves too. The library cache lock was on the queue STRMADMIN.STREAMSOUT_DAILY and the owner of the lock was process J000 that was stucked 'single-task message'. From the information on the systemstate dump we can see that this process has been on that situation for more than 3 days and 20 hours. Based on the call stack it seems that the process was about or in the middle of a call to a listener. DIAGNOSTIC ANALYSIS: -------------------- Files to be uploaded: USA: - RDA.zip , RDA node 1 - GCTGCMU1_healthchk.html, streams healthcheck node 1 - GCTGCMU1_healthchk.html, streams healthcheck node 2 - gctgcmu2_ora_21349.trc, hanganalyze and systemstate dumps when the hang is ocurring. Node 2 - gctgcmu1_ora_858.trc, hanganalyze and systemstate dumps when the hang is ocurring. Node 1. HKG: - alert_GCTHKGU1.log, alert log file node 1 - alert_GCTHKGU2.log, alert log file node 2 - listener_hkg0223xus.log_20060320, listener log file node 1. - listener_hkg0224xus.log_20060319, listener log file node 2. LON: - alert_GCTLONU1.log, alert log file node 1 - alert_GCTLONU2.log, alert log file node 2 - listener_lon0223xus.log_20060318, listener log file node 1. - listener_lon3166xus.log_20060320, listener log file node 2. Hang was identified at USA on node 1. Analysis of gctgcmu1_ora_858.trc: System State 1 ~~~~~~~~~~~~~~ 21: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=21 42: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=404 51: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=17 67: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=90 71: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=56 76: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=344 Cmd: PL/SQL Execute 77: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=87 System State 2 ~~~~~~~~~~~~~~ 21: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=21 42: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=404 51: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=17 67: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=90 71: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=56 76: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=344 Cmd: PL/SQL Execute 77: waiting for 'library cache lock' [LOCK: handle=25ea4afc8] seq=87 LOCK: handle=25ea4afc8 QUEU:STRMADMIN.STREAMSOUT_DAILY Resource Holder State LOCK: handle=25ea4afc8 50: waiting for 'single-task message' PROCESS 50: ~~~~~~~~~~~ OSD pid info: Unix process pid: 12949, image: oracle@slodb001 (J000) From the call stack looks like process was doing an SQL*Net connection to a listenerand doing this connection we get hanged because the stack trace is the same for the two process dumps shown on both system states. (session) oct: 0, prv: 0, sql: (nil), psql: (nil), user: 92/STRMADMIN waiting for 'single-task message' blocking sess=0x(nil) seq=5 wait_time=0 seconds since wait started=332308 =0, =0, =0 It is running a propagation job: next_date := sys.dbms_aqadm.aq$_propaq(job); Knowing that the seconds in wait are 332308 and the dump of the process occurred on 2006-03-21 08:15:12.640, this process is waiting on this event: 1. On USA the process is waiting since 17-MAR-2006 11:56:44 2. That time on London is 17-MAR-2006 16:56:44 3. That time on HONG KONG is 18-MAR-2006 01:56:44 At that time nothing relevant was found on alert log files on listener log files. Processes waiting on library cache lock ~~~~~~~~~~~~~~~ 21 (PZ99) : Slave of J002 42 (q004) : Slave of process 44 (QMNC) 51 (J001) : 67 (q003) : Slave of process 44 (QMNC) 71 (q005) : Slave of process 44 (QMNC) 51 (TNS shadow) : 77 (q007) : Slave of process 44 (QMNC) WORKAROUND: ----------- No workaround found so far. Killing the process or bouncing instance should solve the problem. RELATED BUGS: ------------- No similar bugs found. This environment is also involved on bug 5089630 REPRODUCIBILITY: ---------------- Problem has reproduced just one time on customer site. TEST CASE: ---------- STACK TRACE: ------------ For processes waiting on library cache lock we can see different call stacks, here is the one for process 21: ksdxfstk ksdxcb sspuser pthread_sighandler_rt GI___libc_sigaction GI___poll kslwait kjusuc ksipgetctx kqlmli kgllkal kglget kglgob kwqicgob kwqicrqo0 kwqmsnrmsg kwqsldqs kwqsif qerfxFetch qervwFetch qertqoFetch qerpxSlaveFetch qerpxFetch opiexe kpoal8 opiodr kpoodr upirtrc kpurcsc kpuexecv8 kpuexec OCIStmtExecute kxfxsStmtExecute kxfxsExecute kxfxsp kxfxmai kxfprdp opirip opidrv sou2o opimai_real main __libc_start_main _start For process waiting on single-task message, we can see the following call stack: ksdxfstk ksdxcb sspuser pthread_sighandler_rt GI___libc_sigaction GI___poll clntudp_call do_ypcall yp_match internal_gethostbyname2_r nss_nis_gethostbyname_r gethostbyname_r gethostbyname snlpcgthstbynm snlinGetAddrInfo nttbnd2addr ntacbbnd2addr ntacbnd2addr nsc2addr nscall1 nscall niotns nigcall osncon kpkiadef upiini upiah0 kpuatch OCIServerAttach kpnconn npicon0 kpndbcon OCIKDBLinkConn2 OCIKDBLinkConn kwqpcon kwqpgps spefmccallstd pextproc peftrusted psdexsp rpiswu2 psdextp pefccal pefca pevm_FCAL pfrinstr_FCAL pfrrun_no_tool pfrrun plsql_run peicnt kkxexe opiexe opiodr rpidrus skgmstack rpidru rpiswu2 rpidrv rpiexe kkjex1e kkjsexe kkjrdp opirip opidrv sou2o opimai_real main libc_start_main start I do not see any Oracle bug here but it is hard to be certain without the SQLNET.ORA settings and multiple snapshots of the problem process. It is quite valid for an Oracle session to be holding a library cache lock when it makes an outbound DBlink call. If another session wants that lock in an incompatible mode then it has to wait. In this case the blocking session making the outbound link call appears from the one stack dump to be in OS code under gethostbyname(). However it could have been spinning down the stack in Oracle code but I cannot comment on the info we have. The "single-task message" wait event is started / ended in kpnconn() so if there was a "spin" it would have to be above that point in the stack. In 10.2 there is the option to configure NET to timeout on outbound connect attempts by setting SQLNET.OUTBOUND_CONNECT_TIMEOUT = N seconds. The timeout occurs in niotns() in the stack so if this is set you would expect a session in this state to then timeout which may be useful if there are underlying issues with TCP hostname resolution. (Watch out for bug 4933023 if you use this SQLNET parameter). If the issue recurs then get CPU usage info, multiple stacks and you may want to attach with gdb and see if the code ever returns above gethostbyname or not to get an idea if this Sorry , my explanation is probably not clear . Here is the stack you have but annotated: Callback to get the short stack. Confirms we are not HUNG in a device driver. ksdxfstk ksdxcb sspuser pthread_sighandler_rt GI___libc_sigaction Inside OS supplied code executing gethostbyname() C call. GI___poll clntudp_call do_ypcall yp_match internal_gethostbyname2_r nss_nis_gethostbyname_r gethostbyname_r gethostbyname Oracle Net code: snlpcgthstbynm snlinGetAddrInfo nttbnd2addr ntacbbnd2addr ntacbnd2addr nsc2addr nscall1 nscall niotns <<< This is where SQLNET.OUTBOUND_CONNECT_TIMEOUT is implemented IF it has been configured. nigcall Oracle RDBMS code: osncon kpkiadef upiini upiah0 kpuatch OCIServerAttach kpnconn <<< This is where "single-task message" starts/ends npicon0 ... If we just get two stack snapshots of the process, as was the case, and both have the above stack then we can say: As the "seq=" of both snaps is the same (5) then we did not return below kpnconn() in the call stack. But as poll() is typically a blocking call, even if only for a short time, then we cannot be sure if this process was blocked permanently in the poll() waiting on some large timout or similar, or if the code was executing and looping. If it was looping it could have done so at any point on the above stack down to kpnconn() where we would have changed the seq# on the wait event if we exited here. We can say that as the short stack dump triggered a callout then the Linux kernel was not stuck inside a device driver. We can also say it looks like the gethostbyname is in YP code doing a UDP call so at OS level you may want to check out the name resolution configuration. You probably dont want to be falling all the way back to UDP requests to get hostnames resolved. So if the problem recurs it would help to get: ps information of the process (to see if it uses CPU at all) strace for a few minutes - this should help show if the process is entering / leaving any system call (eg: poll) A full call stack with arguments from either gdb or errorstack and these should help show the arguments passed up the stack. In gdb you can also do something like attach to the problem process and : break osncon break nigcall break niotns etc.. up the stack to gethostbyname and then "cont" and it should stop if it enters into those functions from below helping indicate a spin/loop point below that point. It may also be worth getting Linux "crash" information for the process to see what the process looks like from the Linux side but follow up with the OS team on that side. SQLNET.OUTBOUND_CONNECT_TIMEOUT is a backup mechanism to help prevent
This note claimed that one session may hold library cache lock , and wait in single-task message after it makes an outbound DBlink call.If another session wants that lock in an incompatible mode then it has to wait. The "single-task message" wait event is started / ended in kpnconn() so if there was a "spin" it would have to be above that point in the stack. Oracle support advise to set SQLNET.OUTBOUND_CONNECT_TIMEOUT so that we can expect a session in this state to then timeout which may be useful if there are underlying issues with TCP hostname resolution. The principle in these cases is identical. Do deep digging ,you can see this Knowledge:
Hdr: 8427478 10.2.0.3 RDBMS 10.2.0.3 PI/DISTRIB PRODID-5 PORTID-23 ORA-12170 Abstract: WHEN USING DBLINK,IT CONNECT TWICE AND TAKE DOBULE-TIME FOR TIME-OUT( ORA-12170) PROBLEM: -------- When client connect to database using TCP/IP, if there are some problems in the network and server , The client recevies ORA-12170 (ETIMEDOUT) The timeout time is depend on OS TCP parameter.(e.g. tcp_syn_retries parameter on Linux platform). ERROR: ORA-12170 : TNS:Connect timeout occurred ** sqlnet.log *************************************************** VERSION INFORMATION: TNS for Linux: Version 10.2.0.3.0 - Production TCP/IP NT Protocol Adapter for Linux: Version 10.2.0.3.0 - Production Time: 10-APR-2009 21:38:41 Tracing not turned on. Tns error struct: ns main err code: 12535 TNS-12535: TNS:operation timed out ns secondary err code: 12560 nt main err code: 505 TNS-505: Operation timed out nt secondary err code: 110 <= ETIMEDOUT nt OS err code: 0 Client address: ** sqlnet.log *************************************************** client server | | connect() | |-------x-->|-------- | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | |when setting tcp_syn_retries=5(default) |-------x-->| | It takes about 189 seconds for time-out. | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | --------------------- ORA-12170 occur. But, the connection via DBLINK, it sometimes try to connect twice. and it takes double-time for time-out. local site remote site | | connect() | |-------x-->|-------- | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | ORA-12170 occur ,but it not returning to client. and server process of local site try to connect automatically.(2nd connect) connect() | | |-------x-->| | | SYN | | |-------x-->| | It takes about 378 seconds for time-out. | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | |-------x-->| | | SYN | | --------------------- ORA-12170 occur. The problem is that it takes dobule-time by this behavior using DBLINK. DIAGNOSTIC ANALYSIS: -------------------- We got stack trace when trying connect. 1st connect connect()+36 alter system flush shared_pool;
You can find the kpnconn call in stack trace , so the single-task message may occur in two time dblink reconnect and take a long time. The document provide one workaround way: flush shared_pool.which I suspected. In summary , still no Mature program to resolve this problem , All we can do is pray. In my opinion , Version 10.2.0.4 is stable enough within most layer , but still a lots of bug or unexpected behavior reside in K2(kernel Distributed Execution Layer). Distributed system is a really complicated subject in computer science.
一、系统分层功能 感知层:用实验箱的两个传感器模块 传感器 1:温湿度传感器,采集温度、湿度数据。 传感器 2:红外对射 ,采集触发状态。 网络层: Zigbee 通信:传感器 1、2 的数据,经 Zigbee 节点传给协调器,协调器通过串口发 PC 端。 数据处理:解析串口数据,分主题发 MQTT 网络,或存数据库 。 应用层:用 Python 做终端,实现界面、串口、数据库交互(可加 MQTT),完成这些功能: 二、具体功能 数据上传: 远程设备实时收传感器 1 数据,格式:学号姓名缩写+温度+湿度 。 远程设备实时收传感器 2 数据,格式:学号姓名缩写+传感器名+interrupt 。 Mysql 数据库:建不同数据表存两个传感器数据,表含 学号姓名缩写、传感器名、数据值、传感器状态 等字段 。 命令下发: 发 学号姓名缩写+Num1Led+on ,传感器 1 连的 Zigbee 模块 LED2 亮;发 ...+off 则灭 。 发 学号姓名缩写+Num2Led+on ,传感器 2 连的 Zigbee 模块 LED2 亮;发 ...+off 则灭 。 数据联动: 传感器 1:温度>25 且湿度>60,其连的 Zigbee 模块 LED2 闪烁,远程设备、数据库表显示 “温湿度异常”;恢复后显示 “异常解除” 。 传感器 2:触发超 5 次,其连的 Zigbee 模块 LED2 闪烁,远程设备、数据库表显示 “传感状态异常”;恢复后显示 “传感异常解除” 。 强制解除:发 学号姓名缩写+Num1Led+relie ,传感器 1 连的 LED2 停闪,设备和表显示 “强制异常解除温湿度” ;发 ...+Num2Led+relie 同理。 数据展示:Python 界面里,串口控制,实时显示传感器 1 的 学号姓名缩写、温度、湿度 数据,呈现底层传感器联动状态 。 #include <stdio.h> #include <string.h> #include "OSAL.h" #include "ZGlobals.h" #include "AF.h" #include "aps_groups.h" #include "ZDApp.h" #include "MT_UART.h" //???? #include "SampleApp.h" #include "SampleAppHw.h" #include "OnBoard.h" /* HAL */ #include "hal_lcd.h" #include "hal_led.h" #include "hal_key.h" #include "hal_uart.h" #include "hal_mcu.h" #include "sht11.h" // P1 interrupt vector value is already defined in ioCC2530.h // #define P1INT_VECTOR 0x7B // Commented out to avoid redefinition warning // Sensor type configuration: // Combined sensor: supports both temp/humidity and IR sensor functions // sht11 command activates temp/humidity sensor, interrupt command activates IR sensor //#define COMBINED_SENSOR // Single sensor configuration (optional): //#define TEMP_HUMIDITY_SENSOR // Temperature/humidity sensor only // Default: IR sensor only (no macro defined) /********************************************************************* * CONSTANTS */ /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ // This list should be filled with Application specific Cluster IDs. const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] = { SAMPLEAPP_PERIODIC_CLUSTERID, SAMPLEAPP_FLASH_CLUSTERID, SAMPLEAPP_BUZZER_CLUSTERID, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, }; // Add function declarations at the top of the file, after other declarations void SetBuzzerStatus(uint8 status); void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg); void InitIRSensorInterrupt(void); void ProcessIRSensorInterrupt(void); void ProcessLED2Flash(void); // LED2闪烁处理函数 void PrintDeviceInfo(void); // 打印设备信息 void PrintHexBytes(const char* title, const char* data, uint8 len); // 十六进制打印辅助函数 const SimpleDescriptionFormat_t SampleApp_SimpleDesc = { SAMPLEAPP_ENDPOINT, // int Endpoint; SAMPLEAPP_PROFID, // uint16 AppProfId[2]; SAMPLEAPP_DEVICEID, // uint16 AppDeviceId[2]; SAMPLEAPP_DEVICE_VERSION, // int AppDevVer:4; SAMPLEAPP_FLAGS, // int AppFlags:4; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; (cId_t *)SampleApp_ClusterList, // uint8 *pAppInClusterList; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumOutClusters; (cId_t *)SampleApp_ClusterList // uint8 *pAppOutClusterList; }; // This is the Endpoint/Interface description. It is defined here, but // filled-in in SampleApp_Init(). Another way to go would be to fill // in the structure here and make it a "const" (in code space). The // way it's defined in this sample app it is define in RAM. endPointDesc_t SampleApp_epDesc; // Add global variable to control temperature and humidity reading static uint8 g_bReadTempHumi = 0; // Add IR sensor status variable static uint8 g_IRSensorStatus = 0; // Add sensor type variable - configure this based on device type // For combined sensor nodes, set to SENSOR_TYPE_COMBINED // For temperature/humidity sensor nodes, set to SENSOR_TYPE_TEMP_HUMIDITY // For IR sensor nodes, set to SENSOR_TYPE_IR #ifdef COMBINED_SENSOR static uint8 g_SensorType = SENSOR_TYPE_COMBINED; #elif defined(TEMP_HUMIDITY_SENSOR) static uint8 g_SensorType = SENSOR_TYPE_TEMP_HUMIDITY; #else static uint8 g_SensorType = SENSOR_TYPE_IR; #endif // 添加全局变量,用于防止中断处理函数重入 static uint8 g_IRProcessingInProgress = 0; // 添加控制LED2闪烁的全局变量 static uint8 g_LED2FlashStatus = 0; // 0: 停止闪烁, 1: 闪烁中 // 定义命令字符串常量,避免硬编码字符串和在函数调用中重复创建 const char* CMD_NUM1LED_ON = "42213238YFC+Num1Led+on"; const char* CMD_NUM1LED_OFF = "42213238YFC+Num1Led+off"; const char* CMD_NUM2LED_ON = "42213238YFC+Num2Led+on"; const char* CMD_NUM2LED_OFF = "42213238YFC+Num2Led+off"; const char* CMD_ON = "on"; const char* CMD_OFF = "off"; const char* CMD_HT = "ht"; const char* CMD_HF = "hf"; const char* CMD_FLASH = "flash"; // 闪烁命令 const char* CMD_RELIE = "42213238YFC+Num1Led+relie"; // 停止闪烁命令 const char* CMD_SHUO = "shuo"; // 红外对射传感器闪烁命令 const char* CMD_IR_RELIE = "42213238YFC+Num2Led+relie"; // 红外对射传感器停止闪烁命令 /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ uint8 SampleApp_TaskID; // Task ID for internal task/event processing // This variable will be received when // SampleApp_Init() is called. devStates_t SampleApp_NwkState; uint8 SampleApp_TransID; // This is the unique message ID (counter) afAddrType_t SampleApp_Periodic_DstAddr; afAddrType_t SampleApp_Flash_DstAddr; aps_Group_t SampleApp_Group; uint8 SampleAppPeriodicCounter = 0; uint8 SampleAppFlashCounter = 0; /********************************************************************* * LOCAL FUNCTIONS */ void SampleApp_HandleKeys( uint8 shift, uint8 keys ); void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pckt ); void SampleApp_SendPeriodicMessage( void ); void SampleApp_SendFlashMessage( uint16 flashTime ); /********************************************************************* * NETWORK LAYER CALLBACKS */ /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn SampleApp_Init * * @brief Initialization function for the Generic App Task. * This is called during initialization and should contain * any application specific initialization (ie. hardware * initialization/setup, table initialization, power up * notificaiton ... ). * * @param task_id - the ID assigned by OSAL. This ID should be * used to send messages and set timers. * * @return none */ void SampleApp_Init( uint8 task_id ) { SampleApp_TaskID = task_id; SampleApp_NwkState = DEV_INIT; SampleApp_TransID = 0; // Device hardware initialization can be added here or in main() (Zmain.c). // If the hardware is application specific - add it here. // If the hardware is other parts of the device add it in main(). // Initialize IR sensor interrupt InitIRSensorInterrupt(); #if defined ( BUILD_ALL_DEVICES ) // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered // together - if they are - we will start up a coordinator. Otherwise, // the device will start as a router. if ( readCoordinatorJumper() ) zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; else zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; #endif // BUILD_ALL_DEVICES #if defined ( HOLD_AUTO_START ) // HOLD_AUTO_START is a compile option that will surpress ZDApp // from starting the device and wait for the application to // start the device. ZDOInitDevice(0); #endif // Setup for the periodic message's destination address // Broadcast to everyone SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF; // Setup for the flash command's destination address - Group 1 SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; // Fill out the endpoint description. SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_epDesc.task_id = &SampleApp_TaskID; SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; SampleApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SampleApp_epDesc ); // Register for all key events - This app will handle all key events RegisterForKeys( SampleApp_TaskID ); MT_UartRegisterTaskID( SampleApp_TaskID ); //add by 1305106 // By default, all devices start out in Group 1 SampleApp_Group.ID = 0x0001; osal_memcpy( SampleApp_Group.name, "Group 1", 7 ); aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); #if defined ( LCD_SUPPORTED ) HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 ); #endif // 打印设备类型和传感器类型信息 PrintDeviceInfo(); } /********************************************************************* * @fn SampleApp_ProcessEvent * * @brief Generic Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return none */ uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // Received when a key is pressed case KEY_CHANGE: SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; // Received when a messages is received (OTA) for this endpoint case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt ); break;; case SPI_INCOMING_ZAPP_DATA: SampleApp_ProcessMTMessage(MSGpkt); MT_UartAppFlowControl (MT_UART_ZAPP_RX_READY); break; // Received whenever the device changes state in the network case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); Sht11Init(); if ( (SampleApp_NwkState == DEV_ZB_COORD) || (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) ) { // Start sending the periodic message in a regular interval. HalLedSet(HAL_LED_1, HAL_LED_MODE_ON); osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); } else { // Device is no longer in the network } break; default: break; } osal_msg_deallocate( (uint8 *)MSGpkt ); MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); } return (events ^ SYS_EVENT_MSG); // return unprocessed events } // Send a message out - This event is generated by a timer // (setup in SampleApp_Init()). if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) { SampleApp_SendPeriodicMessage(); // Send the periodic message // Setup to send message again in normal period (+ a little jitter) osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); // return unprocessed events } // Process IR sensor interrupt event if ( events & SAMPLEAPP_SEND_SENSOR_INT_EVT ) { ProcessIRSensorInterrupt(); return (events ^ SAMPLEAPP_SEND_SENSOR_INT_EVT); } // 处理LED2闪烁事件 if ( events & SAMPLEAPP_LED2_FLASH_EVT ) { // 添加调试输出 char buf[100]; sprintf(buf, "处理LED2闪烁事件, g_LED2FlashStatus=%d, g_SensorType=%d\r\n", g_LED2FlashStatus, g_SensorType); HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 检查是否是温湿度传感器或红外对射传感器,且闪烁标志为1 if (g_LED2FlashStatus == 1 && (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY || g_SensorType == SENSOR_TYPE_IR)) { // 执行闪烁处理函数 ProcessLED2Flash(); // 不需要在这里设置下一次闪烁计时器,已在ProcessLED2Flash函数中处理 } else { // g_LED2FlashStatus不为1时,确保LED2关闭 if (g_LED2FlashStatus == 0) { HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); HalUARTWrite(0, (uint8*)"闪烁标志为0,停止闪烁并关闭LED2\r\n", 32); } } return (events ^ SAMPLEAPP_LED2_FLASH_EVT); } return 0; // Discard unknown events } /********************************************************************* * Event Generation Functions */ /********************************************************************* * @fn SampleApp_HandleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ void SampleApp_HandleKeys( uint8 shift, uint8 keys ) { (void)shift; // Intentionally unreferenced parameter if ( keys & HAL_KEY_SW_6 ) { /* This key sends the Flash Command is sent to Group 1. * This device will not receive the Flash Command from this * device (even if it belongs to group 1). */ SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION ); } if ( keys & HAL_KEY_SW_2 ) { /* The Flashr Command is sent to Group 1. * This key toggles this device in and out of group 1. * If this device doesn't belong to group 1, this application * will not receive the Flash command sent to group 1. */ aps_Group_t *grp; grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP ); if ( grp ) { // Remove from the group aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP ); } else { // Add to the flash group aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); } } } /********************************************************************* * LOCAL FUNCTIONS */ /********************************************************************* * @fn SampleApp_MessageMSGCB * * @brief Data message processor callback. This function processes * any incoming data - probably from other devices. So, based * on cluster ID, perform the intended action. * * @param none * * @return none */ void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; uint8 *buf; switch(pkt->clusterId) { case SAMPLEAPP_PERIODIC_CLUSTERID: buf = pkt->cmd.Data; if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { // Coordinator received data from end device if(pkt->cmd.DataLength == 4 && buf[0] <= 100) { // Format and print temperature data char tempStr[50]; sprintf(tempStr, "42213238YFC+温湿度传感器+温度:%d.%d C+湿度:%d.%d%%\r\n", buf[0], buf[1], buf[2], buf[3]); HalUARTWrite(0, (uint8*)tempStr, strlen(tempStr)); } else if(pkt->cmd.DataLength == 2 && buf[0] == 0x02) { // Process IR sensor data char irStr[50]; if(buf[1] == 0x01) { sprintf(irStr, "IR Sensor Node: Obstacle Detected!\r\n"); } else { sprintf(irStr, "IR Sensor Node: No Obstacle\r\n"); } HalUARTWrite(0, (uint8*)irStr, strlen(irStr)); } else if(pkt->cmd.DataLength == 3 && buf[0] == 0x03) { // Process interrupt message from end device if(buf[1] == 0x01) { // Coordinator prints the message and also blinks LED2 HalUARTWrite(0, (uint8*)"42213238YFC+红外对射传感器+interrupt\r\n", 36); // Flash LED2 10 times on coordinator as well HalLedBlink(HAL_LED_2, 10, 50, 200); } } else if(pkt->cmd.DataLength == 2 && buf[0] == 0x04) { // Process sensor identification response uint8 sensorType = buf[1]; char coordMsg[80]; uint16 srcAddr = pkt->srcAddr.addr.shortAddr; if(sensorType == SENSOR_TYPE_TEMP_HUMIDITY) { sprintf(coordMsg, "Device 0x%04X: Temperature/Humidity sensor identified and LED2 activated\r\n", srcAddr); HalUARTWrite(0, (uint8*)coordMsg, strlen(coordMsg)); } else if(sensorType == SENSOR_TYPE_IR) { sprintf(coordMsg, "Device 0x%04X: IR sensor identified and LED2 activated\r\n", srcAddr); HalUARTWrite(0, (uint8*)coordMsg, strlen(coordMsg)); } } } else { // End device received command from coordinator if(pkt->cmd.DataLength == 1) { if(buf[0] == 0x01) { // Start temperature reading g_bReadTempHumi = 1; osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, 1000); } else { // Stop temperature reading g_bReadTempHumi = 0; osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT); } } else if(pkt->cmd.DataLength == 2 && buf[0] == 0x10) { // 处理协调器转发的闪烁命令,仅终端设备响应 if(zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR && g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { if(buf[1] == 0x01) { // 启动LED2闪烁 g_LED2FlashStatus = 1; osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到闪烁命令,启动LED2闪烁\r\n", 30); } else { // 停止LED2闪烁 g_LED2FlashStatus = 0; HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到停止命令,停止LED2闪烁\r\n", 30); } } } // 处理协调器转发的红外对射传感器闪烁命令 else if(pkt->cmd.DataLength == 2 && buf[0] == 0x11) { // 处理协调器转发的红外对射传感器闪烁命令,仅终端设备响应 if(zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR && g_SensorType == SENSOR_TYPE_IR) { if(buf[1] == 0x01) { // 启动红外对射传感器LED2闪烁 g_LED2FlashStatus = 1; osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到红外对射传感器闪烁命令,启动LED2闪烁\r\n", 42); } else { // 停止红外对射传感器LED2闪烁 g_LED2FlashStatus = 0; HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到红外对射传感器停止命令,停止LED2闪烁\r\n", 42); } } } } break; case SAMPLEAPP_FLASH_CLUSTERID: flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2]); HalLedBlink(HAL_LED_4, 4, 50, (flashTime / 4)); break; case SAMPLEAPP_BUZZER_CLUSTERID: SetBuzzerStatus(pkt->cmd.Data[0]); break; case SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID: // Handle sensor identification requests if(zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // This is an end device, check if we should respond uint8 cmd = pkt->cmd.Data[0]; if(cmd == SENSOR_IDENTIFY_CMD_SHT11 && (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY || g_SensorType == SENSOR_TYPE_COMBINED)) { // This is a temperature/humidity sensor or combined sensor responding to sht11 command // Turn on LED2 and send identification response HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); // Send identification response to coordinator uint8 response[2]; response[0] = 0x04; // Sensor identification response // For combined sensor responding to sht11, report as temp/humidity sensor response[1] = SENSOR_TYPE_TEMP_HUMIDITY; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, response, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(cmd == SENSOR_IDENTIFY_CMD_INTERRUPT && (g_SensorType == SENSOR_TYPE_IR || g_SensorType == SENSOR_TYPE_COMBINED)) { // This is an IR sensor or combined sensor responding to interrupt command // Turn on LED2 and send identification response HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); // Send identification response to coordinator uint8 response[2]; response[0] = 0x04; // Sensor identification response // For combined sensor responding to interrupt, report as IR sensor response[1] = SENSOR_TYPE_IR; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, response, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(cmd == 0x05 && (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY || g_SensorType == SENSOR_TYPE_COMBINED)) { // Turn off LED2 for temperature/humidity sensors HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } else if(cmd == 0x06 && (g_SensorType == SENSOR_TYPE_IR || g_SensorType == SENSOR_TYPE_COMBINED)) { // Turn off LED2 for IR sensors HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } } break; } } /********************************************************************* * @fn SampleApp_SendPeriodicMessage * * @brief Send the periodic message. * * @param none * * @return none */ void SampleApp_SendPeriodicMessage(void) { if(g_bReadTempHumi) { uint8 temp_int, temp_dec, humi_int, humi_dec; char buf[50]; float humi, temp; // Initialize SHT11 sensor Sht11Init(); if(GetHumiAndTemp(&humi, &temp) == 0) { // Convert float to integer parts temp_int = (uint8)temp; temp_dec = (uint8)((temp - temp_int) * 10); humi_int = (uint8)humi; humi_dec = (uint8)((humi - humi_int) * 10); // Format the message sprintf(buf, "42213238YFC+温湿度传感器+温度:%d.%d C+湿度:%d.%d%%\r\n", temp_int, temp_dec, humi_int, humi_dec); // Send to UART HalUARTWrite(0, (uint8*)buf, strlen(buf)); // Prepare network data packet buf[0] = temp_int; buf[1] = temp_dec; buf[2] = humi_int; buf[3] = humi_dec; // Send data to network and check result afStatus_t status = AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 4, // Only send 4 bytes of data (uint8*)buf, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); // 只记录错误但不中断流程,保持原有功能不变 if (status != afStatus_SUCCESS) { // 可以在这里添加错误处理代码,如重试或记录日志 // 但不要中断原有功能流程 } } // Restart timer for next reading osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, 2000); // Read every 2 seconds } } /********************************************************************* * @fn SampleApp_SendFlashMessage * * @brief Send the flash message to group 1. * * @param flashTime - in milliseconds * * @return none */ void SampleApp_SendFlashMessage( uint16 flashTime ){ uint8 buffer[3]; buffer[0] = (uint8)(SampleAppFlashCounter++); buffer[1] = LO_UINT16( flashTime ); buffer[2] = HI_UINT16( flashTime ); if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc, SAMPLEAPP_FLASH_CLUSTERID, 3, buffer, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { } else { // Error occurred in request to send. } } void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg) { // 增加安全检查,确保msg指针有效 if(msg == NULL) { return; } const char *msgPtr = ((const char *)msg+2); uint8 status; // 调试输出,打印收到的命令 HalUARTWrite(0, (uint8*)"收到命令: ", 10); HalUARTWrite(0, (uint8*)msgPtr, strlen(msgPtr)); HalUARTWrite(0, (uint8*)"\r\n", 2); // 打印命令的十六进制值,帮助调试 PrintHexBytes("命令十六进制", msgPtr, strlen(msgPtr)); // 打印预期命令常量进行比较 char buf[100]; sprintf(buf, "预期relie命令: %s, 长度: %d\r\n", CMD_RELIE, strlen(CMD_RELIE)); HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 打印预期命令的十六进制值 PrintHexBytes("预期十六进制", CMD_RELIE, strlen(CMD_RELIE)); // 使用更安全的字符串比较方式 if(strncmp(msgPtr, CMD_NUM1LED_OFF, strlen(CMD_NUM1LED_OFF)) == 0) { // Send command to turn off LED2 for temperature/humidity sensors uint8 cmd[2]; cmd[0] = 0x05; // LED control command cmd[1] = 0x00; // Turn off LED2 for temp/humidity sensors AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_NUM2LED_OFF, strlen(CMD_NUM2LED_OFF)) == 0) { // Send command to turn off LED2 for IR sensors uint8 cmd[2]; cmd[0] = 0x06; // LED control command cmd[1] = 0x00; // Turn off LED2 for IR sensors AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_ON, strlen(CMD_ON)) == 0) { status = 0x01; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_BUZZER_CLUSTERID, 1, &status, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_OFF, strlen(CMD_OFF)) == 0) { status = 0x00; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_BUZZER_CLUSTERID, 1, &status, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_HT, strlen(CMD_HT)) == 0) { // Forward the command to end device uint8 cmd = 0x01; // Command for starting temperature reading AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_HF, strlen(CMD_HF)) == 0) { // Forward the command to end device uint8 cmd = 0x00; // Command for stopping temperature reading AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_NUM1LED_ON, strlen(CMD_NUM1LED_ON)) == 0) { // Send sensor identification request for temperature/humidity sensors uint8 cmd = SENSOR_IDENTIFY_CMD_SHT11; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_NUM2LED_ON, strlen(CMD_NUM2LED_ON)) == 0) { // Send sensor identification request for IR sensors uint8 cmd = SENSOR_IDENTIFY_CMD_INTERRUPT; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_FLASH, strlen(CMD_FLASH)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"收到flash命令\r\n", 14); // 只有温湿度传感器模块响应flash命令 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是温湿度传感器模块\r\n", 25); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行闪烁,协调器不闪烁 // 启动LED2闪烁 g_LED2FlashStatus = 1; // 触发闪烁事件,立即开始 osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"终端设备开始LED2闪烁\r\n", 24); } else { // 协调器接收到flash命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x10; // 自定义的flash命令标识 cmd[1] = 0x01; // 开始闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发flash命令到网络\r\n", 27); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是温湿度传感器模块,忽略命令\r\n", 32); } } else if(strncmp(msgPtr, CMD_RELIE, strlen(CMD_RELIE)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"匹配到relie命令\r\n", 17); // 只有温湿度传感器模块响应relie命令 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是温湿度传感器模块\r\n", 25); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"终端设备停止LED2闪烁\r\n", 24); } else { // 协调器接收到relie命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x10; // 自定义的flash命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发停止闪烁命令到网络\r\n", 31); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是温湿度传感器模块,忽略命令\r\n", 32); } } // 添加对红外对射传感器停止闪烁命令的处理 else if(strncmp(msgPtr, CMD_IR_RELIE, strlen(CMD_IR_RELIE)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"匹配到红外对射停止闪烁命令\r\n", 29); // 只有红外对射传感器模块响应停止闪烁命令 if (g_SensorType == SENSOR_TYPE_IR) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是红外对射传感器模块\r\n", 27); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射终端设备停止LED2闪烁\r\n", 31); } else { // 协调器接收到停止闪烁命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x11; // 自定义的红外闪烁命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发红外对射停止闪烁命令到网络\r\n", 38); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是红外对射传感器模块,忽略命令\r\n", 34); } } // 尝试直接匹配红外对射传感器停止闪烁命令 else if(strcmp(msgPtr, "42213238YFC+Num2Led+relie") == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"直接匹配到红外对射停止闪烁命令\r\n", 33); // 只有红外对射传感器模块响应停止闪烁命令 if (g_SensorType == SENSOR_TYPE_IR) { if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射终端设备直接停止LED2闪烁\r\n", 35); } else { // 协调器接收到停止闪烁命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x11; // 自定义的红外闪烁命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器直接转发红外对射停止闪烁命令到网络\r\n", 42); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } } // 尝试另一种方式匹配温湿度传感器的relie命令(恢复原有逻辑) else if(strcmp(msgPtr, "42213238YFC+Num1Led+relie") == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"直接匹配到温湿度传感器relie命令\r\n", 33); // 只有温湿度传感器模块响应relie命令 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"温湿度传感器终端设备直接停止LED2闪烁\r\n", 39); } else { // 协调器接收到relie命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x10; // 自定义的flash命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器直接转发温湿度传感器停止闪烁命令到网络\r\n", 46); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } } // 添加对shuo命令的处理 - 红外对射传感器LED闪烁命令 else if(strncmp(msgPtr, CMD_SHUO, strlen(CMD_SHUO)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"收到shuo命令\r\n", 14); // 只有红外对射传感器模块响应shuo命令 if (g_SensorType == SENSOR_TYPE_IR) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是红外对射传感器模块\r\n", 27); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行闪烁,协调器不闪烁 // 启动LED2闪烁 g_LED2FlashStatus = 1; // 触发闪烁事件,立即开始 osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射终端设备开始LED2闪烁\r\n", 30); } else { // 协调器接收到shuo命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x11; // 自定义的红外闪烁命令标识,与温湿度传感器区分 cmd[1] = 0x01; // 开始闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发shuo命令到网络\r\n", 27); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是红外对射传感器模块,忽略命令\r\n", 34); } } } // Initialize IR sensor interrupt function void InitIRSensorInterrupt(void) { // Set P1_2 as input pin P1DIR &= ~BV(2); // Configure P1_2 as input P1SEL &= ~BV(2); // Set as general I/O, not peripheral function // Configure P1_2 as pull-up input P1INP &= ~BV(2); // Set as tri-state input P2INP &= ~BV(5); // Clear P1 port pull-down setting, configure as pull-up // Read current status g_IRSensorStatus = (P1 & BV(2)) ? 0 : 1; // Set P1_2 as falling edge triggered PICTL |= BV(1); // P1 port uses falling edge trigger (PICTL.P1ICON = 1) // Enable P1_2 interrupt P1IEN |= BV(2); // Enable P1_2 interrupt function // Clear possible interrupt flags P1IFG &= ~BV(2); // Enable P1 port interrupt IEN2 |= BV(4); // Enable P1 port interrupt (IEN2.P1IE = 1) } // Process IR sensor interrupt function void ProcessIRSensorInterrupt(void) { // 简单的重入保护:如果已经在处理中,则退出 if(g_IRProcessingInProgress) { return; } g_IRProcessingInProgress = 1; // 设置处理中标志 // Read current status uint8 currentStatus = (P1 & BV(2)) ? 0 : 1; // For end devices, flash LED2 10 times and send interrupt message to coordinator if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // Flash LED2 10 times on end device only HalUARTWrite(0, (uint8*)"42213238YFC+红外对射传感器+interrupt\r\n", 36); HalLedBlink(HAL_LED_2, 10, 50, 200); uint8 buf[3]; buf[0] = 0x03; // Indicates this is an interrupt event message buf[1] = 0x01; // Interrupt occurred buf[2] = currentStatus; // Current sensor status AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 3, (uint8*)buf, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } // Status changed if (currentStatus != g_IRSensorStatus) { g_IRSensorStatus = currentStatus; // Send status to coordinator if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { uint8 buf[2]; buf[0] = 0x02; // Indicates this is IR sensor data buf[1] = g_IRSensorStatus; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, (uint8*)buf, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } // Re-enable interrupt after processing // Clear interrupt flag P1IFG &= ~BV(2); // Re-enable interrupt P1IEN |= BV(2); g_IRProcessingInProgress = 0; // 清除处理中标志 } // LED2闪烁处理函数 void ProcessLED2Flash(void) { // 添加调试输出 HalUARTWrite(0, (uint8*)"执行LED2闪烁处理函数\r\n", 22); // 判断是温湿度传感器还是红外对射传感器 if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 温湿度传感器模块执行闪烁 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY && g_LED2FlashStatus == 1) { // 添加调试输出 HalUARTWrite(0, (uint8*)"温湿度传感器符合条件,切换LED2状态\r\n", 35); // 切换LED2状态 (开/关) if ((HalLedGetState() & HAL_LED_2) == 0) { HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); HalUARTWrite(0, (uint8*)"温湿度传感器LED2打开\r\n", 22); } else { HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); HalUARTWrite(0, (uint8*)"温湿度传感器LED2关闭\r\n", 22); } // 继续闪烁,500ms后再次触发 osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT, 500); } // 红外对射传感器模块执行闪烁 else if (g_SensorType == SENSOR_TYPE_IR && g_LED2FlashStatus == 1) { // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射传感器符合条件,切换LED2状态\r\n", 37); // 切换LED2状态 (开/关) if ((HalLedGetState() & HAL_LED_2) == 0) { HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); HalUARTWrite(0, (uint8*)"红外对射传感器LED2打开\r\n", 24); } else { HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); HalUARTWrite(0, (uint8*)"红外对射传感器LED2关闭\r\n", 24); } // 继续闪烁,300ms后再次触发(红外传感器闪烁频率比温湿度传感器快一些) osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT, 300); } else { // LED2闪烁状态为0或传感器类型不匹配,不执行闪烁 if (g_LED2FlashStatus == 0) { HalUARTWrite(0, (uint8*)"闪烁状态为0,不执行LED2闪烁\r\n", 29); // 确保LED2处于关闭状态 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } else { // 传感器类型不匹配 HalUARTWrite(0, (uint8*)"传感器类型不匹配,不执行LED2闪烁\r\n", 33); } } } else { // 协调器不执行闪烁 HalUARTWrite(0, (uint8*)"协调器不执行LED2闪烁\r\n", 22); } } // Modify P1 interrupt handler related code, add P1 interrupt service routine HAL_ISR_FUNCTION(halP1Isr, P1INT_VECTOR) { if (P1IFG & BV(2)) { // Clear interrupt flag P1IFG &= ~BV(2); // Notify application to process interrupt via OSAL event osal_set_event(SampleApp_TaskID, SAMPLEAPP_SEND_SENSOR_INT_EVT); } // Clear P1 port interrupt flag P1IF = 0; } // Modify SetBuzzerStatus function to use another pin (P1_0) as buzzer output void SetBuzzerStatus(uint8 status) { if(status == 0x01) { P1_0 = 1; // Use P1_0 as buzzer control pin (active high) } else { P1_0 = 0; // Turn off buzzer } } void PrintDeviceInfo(void) { char buf[80]; // 打印设备类型信息 if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { sprintf(buf, "设备类型: 协调器 (ZG_DEVICETYPE_COORDINATOR)\r\n"); } else if(zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER) { sprintf(buf, "设备类型: 路由器 (ZG_DEVICETYPE_ROUTER)\r\n"); } else if(zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE) { sprintf(buf, "设备类型: 终端设备 (ZG_DEVICETYPE_ENDDEVICE)\r\n"); } else { sprintf(buf, "设备类型: 未知 (%d)\r\n", zgDeviceLogicalType); } HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 打印传感器类型信息 if(g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { sprintf(buf, "传感器类型: 温湿度传感器 (SENSOR_TYPE_TEMP_HUMIDITY)\r\n"); } else if(g_SensorType == SENSOR_TYPE_IR) { sprintf(buf, "传感器类型: 红外传感器 (SENSOR_TYPE_IR)\r\n"); } else if(g_SensorType == SENSOR_TYPE_COMBINED) { sprintf(buf, "传感器类型: 组合传感器 (SENSOR_TYPE_COMBINED)\r\n"); } else { sprintf(buf, "传感器类型: 未知 (%d)\r\n", g_SensorType); } HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 打印编译时定义的宏 #ifdef TEMP_HUMIDITY_SENSOR sprintf(buf, "宏定义: TEMP_HUMIDITY_SENSOR 已定义\r\n"); #else sprintf(buf, "宏定义: TEMP_HUMIDITY_SENSOR 未定义\r\n"); #endif HalUARTWrite(0, (uint8*)buf, strlen(buf)); #ifdef COMBINED_SENSOR sprintf(buf, "宏定义: COMBINED_SENSOR 已定义\r\n"); #else sprintf(buf, "宏定义: COMBINED_SENSOR 未定义\r\n"); #endif HalUARTWrite(0, (uint8*)buf, strlen(buf)); } // 辅助函数,将字符串以十六进制格式打印出来,帮助调试 void PrintHexBytes(const char* title, const char* data, uint8 len) { char buf[200]; uint8 offset = 0; uint8 i; // 打印标题 offset = sprintf(buf, "%s: ", title); // 打印十六进制值 for (i = 0; i < len && offset < 190; i++) { offset += sprintf(buf + offset, "%02X ", (uint8)data[i]); } sprintf(buf + offset, "\r\n"); HalUARTWrite(0, (uint8*)buf, strlen(buf)); } /********************************************************************* *********************************************************************/ 根据要求和代码,实现相关功能,给出修改后的完整代码
最新发布
06-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值