You’re fighting a couple issues here, I believe. I’ll stick to the Grandstream since I’ve got working knowledge of 30/40/60 sets.
Since FPBX/Asterisk is what is generating all of the hints that your BLF keys monitor, it’s what is responsible for changing the color/status of the light. So, it needs to know when a feature is invoked, to them mimic that across the system for anyone who may be monitoring (a subscription to the BLF hint). As you point out, when you do it this way, the actual end-user of the phone in DND doesn’t know DND is active.
When you do it the other way (use the phone’s DND feature), the phone shows a nice big DND icon (on 188.8.131.52 firmware, at least - smaller icon on older firmware). But, the system doesn’t “know” DND for the user has been activated, thus it doesn’t update the BLF keys for other users. This method of DND is actually not very good because although it has a great icon in the display for the user, it’s the actual phone that’s doing all the DND work (this could also be true with the CallFwd feature, depending on how you instruct your users to invoke that feature). This means, if the phone becomes disconnected, the features you’ve activated locally are now disabled (in some cases, may not even reactivate upon boot-up).
So, how do you get the best of both worlds? Easy. These instructions are for 184.108.40.206 (prior releases had the setting in a different place). Under ACCOUNT X>FEATURE CODES, you want to DISABLE the option “Enable Local Call Features”. Make sure when you do this that you have told it all the feature codes to activate/deactivate DND and the various CFWD options, because now that you’ve told the phone not to handle features locally, it will use the pre-programmed codes to invoke the features - all while providing status to the user as if they were operated locally. In other words, if you do this, activating DND on the phone will make the phone dial (on speaker) your DND ON feature code (I recommend setting the advanced optionin FPBX to only play a beep tone for feature code confirmation, since that could get annoying now that you have the phone showing status).
There are a handful of other settings I disable on GS phones, to ensure it’s handing off ALL call control to Asterisk, but for the issue you’re looking to correct, this should take care of what you’re needing.
Sadly, the endpoint module doesn’t auto-fill all the feature codes. I had to make a ton of P-value mappings to the feature code variables, which sucked, but at least the mapping worked.
Hope this helps.